Effective STL 重读笔记——容器

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

1.容器的分类

标准STL序列容器(4)

标准STL关联容器(4)

非标准STL序列容器(2)

非标准STL关联容器(4)

标准非STL容器(6)

可替代的效率更高:

Vector<char>可以作为string,的替代品

Vector可以作为标准关联容器的替代品

2.大多数STL容器的选择标准

3.STL容器新的分类方法:

           连续内存容器

           基于节点的容器

      4.描述一些大多数关于在容器间选择的问题. 略过考虑非STL类容器(比如,数组、bitset)

●你需要“可以在容器的任意位置插入一个新元素”的能力吗?

如果是,你需要序列容器,关联容器做不到。

● 你关心元素在容器中的顺序吗?

如果不,散列容器就是可行的选择。否则,你要避免使用散列容器。

● 必须使用标准C++中的容器吗?

如果是,就可以除去散列容器、slistrope

● 你需要哪一类迭代器?

如果必须是随机访问迭代器,在技术上你就只能限于vectordequestring,但你也可能会考虑rope(关于rope的更多信息在条款50)。如果需要双向迭代器,你就用不了slist(参见条款50)和散列容器的一般实现(参见条款25)。

       当插入或者删除数据时,是否非常在意容器内现有元素的移动?

如果是,你就必须放弃连续内存容器(参见条款5)。

● 容器中的数据的内存布局需要兼容C吗?

如果是,你就只能用vector(参见条款16)。

       查找速度很重要吗?

如果是,你就应该看看散列容器(参见条款25),排序的vector(参见条款23)和标准的关联容器——大概是这个顺序。

       你介意如果容器的底层使用了引用计数吗?

如果是,你就得避开string,因为很多string的实现是用引用计数(参见条款13)。你也不能用rope,因为权威的rope实现是基于引用计数的(参见条款50)。于是你得重新审核你的string,你可以考虑使用vector<char>

       你需要插入和删除的事务性语义吗?也就是说,你需要有可靠地回退插入和删除的能力吗?

如果是,你就需要使用基于节点的容器。如果你需要多元素插入(比如,以范围的方式——参见条款5)的事务性语义,你就应该选择list,因为list是唯一提供多元素插入事务性语义的标准容器。事务性语义对于有兴趣写异常安全代码的程序员来说非常重要。(事务性语义也可以在连续内存容器上实现,但会有一个性能开销,而且代码不那么直观。要了解这方面的知识,请参考Sutter的《Exceptional C++》的条款17[8]。)

       你要把迭代器、指针和引用的失效次数减到最少吗?

如果是,你就应该使用基于节点的容器,因为在这些容器上进行插入和删除不会使迭代器、指针和引用失效(除非它们指向你删除的元素)。一般来说,在连续内存容器上插入和删除会使所有指向容器的迭代器、指针和引用失效。

           你需要具有有以下特性的序列容器吗:1)可以使用随机访问迭代器;2)只要没有删除而且插入只发生在容器结尾,指针和引用的数据就不会失效?

           这个一个非常特殊的情况,但如果你遇到这种情况,deque就是你梦想的容器。(有趣的是,当插入只在容器结尾时,deque的迭代器也可能会失效,deque是唯一一个“在迭代器失效时不会使它的指针和引用失效”的标准STL容器。)

     5.考虑的问题

           元素顺序、标准的一致性、迭代器能力、内存布局和C的兼容性、查找速度、因为引用计数造成的行为不规则、事务性语义的轻松实现和迭代器失效

条款2:小心对“容器无关代码”的幻想

STL是建立在泛化之上的。

数组泛化为容器,参数化了所包含的对象的类型。

函数泛化为算法,参数化了所用的迭代器的类型。

指针泛化为迭代器,参数化了所指向的对象的类型。

 

独立的容器类型泛化为序列或关联容器,而且类似的容器拥有类似的功能。

标准的内存相邻容器(参见条款1)都提供随机访问迭代器,

标准的基于节点的容器(再参见条款1)都提供双向迭代器。

序列容器支持push_frontpush_back,但关联容器不支持。

关联容器提供对数时间复杂度的lower_boundupper_boundequal_range成员函数,但序列容器却没有。

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

      容器容纳了对象,但不是你给它们的那个对象。此外,当你从容器中获取一个对象时,你所得到的对象不是容器里的那个对象。取而代之的是,当你向容器中添加一个对象(比如通过insertpush_back等),进入容器的是你指定的对象的拷贝。拷进去,拷出来。这就是STL的方式。

      拷贝对象是STL的方式。

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

      有效率的取舍

条款5:尽量使用区间成员函数代替他们的单元数兄弟

条款6:警惕C++最令人恼怒的解析

     

条款7:当使用new得指针的容器时,记得在销毁容器前delete那些指针   (看看消除的方式)(还需研究)

条款8:永不建立auto_ptr的容器(还需研究)

条款9:在删除选项中仔细选择          (各种容器的使用是不一样的)

● 去除一个容器中有特定值的所有对象:

    如果容器是vectorstringdeque,使用erase-remove惯用法。

    如果容器是list,使用list::remove

    如果容器是标准关联容器,使用它的erase成员函数。

● 去除一个容器中满足一个特定判定式的所有对象:

    如果容器是vectorstringdeque,使用erase-remove_if惯用法。

    如果容器是list,使用list::remove_if

    如果容器是标准关联容器,使用remove_copy_ifswap,或写一个循环来遍历容器元素,当你把迭代器传给erase时记得后置递增它。

 在循环内做某些事情(除了删除对象之外):

    如果容器是标准序列容器,写一个循环来遍历容器元素,每当调用erase时记得都用它的返回值更新你的迭代器。

    如果容器是标准关联容器,写一个循环来遍历容器元素,当你把迭代器传给erase时记得后置递增它。

 

条款10:注意分配器的协定和约束

条款11:理解自定义分配器的正确用法

条款12:对STL容器线程安全性的期待现实一些

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值