Effective STL 读书笔记

第一章容器

条款1:仔细选择你的容器

C++中各种标准或非标容器:

  • 标准STL序列容器:    vector、string、deque和list(双向列表)。
  • 标准STL管理容器:    set、multiset、map和multimap。
  • 非标准STL序列容器: slist(单向列表)和rope(重型字符串?)。
  • 非标准STL关联容器: hash_set、hash_multiset、hash_map和hash_multimap。(c++11引入了unordered_set、unordered_multiset、unordered_map和unordered_multimap,其亦基于hash表,但属于最新的标准关联容器,所以相对hash_*拥有更高的效率和更好的安全性)
  • 标准非STL容器:        数组(c++11中有新的array标准)、bitset、valarray(用于数值计算,但是一般很少使用)、stack、queue和priority_queue(常用于模拟最大堆和最小堆)
  • 其他:                          vector<char>在某些情况下可以替换string, vector在某些情况下可以替换标准关联容器。

如何选择容器?需要考虑一下几点:是否要求内存连续(随机访问)?是否有频繁的插入/删除?是否要求容器内元素有序?是否有查找速度的要求?本书作者认为没有一个默认容器。(而《c++ primer》认为如果没有非常正当的理由,就应该选vector)

条款2:小心对“容器无关代码”(container-independent code)的幻想

STL是建立在泛型的基础上,但由于不同容器的特性不同(尤其是迭代器、指针和引用的类型与失效规则不同),支持所有容器的相同接口是不存在的。比如:

  • 只有序列容器支持: push_front和push_back,
  • 只有关联容器支持: logN时间复杂度的lower_bound、upper_bound和equal_range;
如果在工程中需要跟换容器类型,可以通过用typedef来减少跟换所带来的代码跟新量。
class Widget { ... };
typedef vector<Widget> WidgetContainer;
typedef WidgetContainer::iterator WCIterator;
WidgetContainer cw;
Widget bestWidget;
...
WCIterator i = find(cw.begin(), cw.end(), bestWidget);
同样,typedef可以用来简化一个经常被运用到的容器的定义,并减少维护的成本。但是typedef只是其他类型的同义字,
如果不想暴露所使用的容器类型,可以将所用的容器封装到一个class中。可以在这个class实现额外的功能,并对原始容器的操作进行封装。

条款3:使容器里对象的拷贝操作轻量而正确

容器内元素的改变、扩充或删除总是伴随着拷贝。如果将一个对象插入容器中,实际上是将这个对象拷贝进这个容器。拷贝是基于此对象对应class的拷贝构造函数和拷贝赋值操作符。

那么问题来了,如果对于某个class来说,他的拷贝非常昂贵,那么拷贝和可能成为容器的瓶颈。此外,拷贝还有可能带来分割的问题,若以基类建立容器,而插入派生类,那么派生部分会被切割。

解决这一问题的一个办法是建立指针的容器,尤其是智能指针的容器。

当然,STL容器在设计时,已经避免了绝大多数无谓的拷贝,相比内置数组,STL vector显然效率更高。

条款4:用empty来代替检查size()是否为0

对于一般的容器,例如vector,v.size()==0 与c.empty()等价。但是对于list来说,l.size()的时间复杂度为o(N)。

理论上,list每次插入元素时,可以跟新其size,这样能够保证l.size()的时间复杂度为o(1)。但list的特殊之处在于splice()成员函数,splice()可以将一个list插入到另一个list中,并且在o(1)内完成。如果需要在调用splice()时跟新size的值,唯一的方法是遍历待插入的list,并计算其长度。换而言之,l.size()和l.splice()之中,只能有一个为o(1)。而在大多数STL的实现中,前者时间复杂度为o(N),而后者时间复杂度为o(1)。

而对于list的empty()的实现,其源代码为


                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值