Effective STL

第一章 容器

第2条:不要试图编写独立于容器类型的代码

首先作者提出,不能尝试泛化出一个适用于所有容器的通用容器。要承认不同容器的不同。容器不是被设计用来交换使用的。
然后,作者提出,实际中,我们肯定会遇到更改已经在大量代码中存在的容器。可以使用封装技术。 书中列出了两种方法:
(1)使用类型定义typedef
class Widget{};
typdef vector<Widget> W;
typedef W::iterator QW;
W cw;
Widget dd;
QW i=find(cw.begin(),cw.end(),dd);


如果更改vector类型,只需要更改一处。
(2)使用类封装
类型定义不能更改用户的使用权限。如果不想把这部分暴露给用户,就应该使用类。。

可以将容器隐藏在一个类中。书中定义了一个类。类中包含一个list类型别名的成员和它的迭代器成员。但是当要使用nth_element时,需要将list改成vector或deque,这样的操作很方便,不会影响被封装在外的用户。但是还需要检查成员函数和友元函数,有没有要更改的内容。


第3条:确保容器中的对象拷贝正确而高效

原因:
(1)STL的插入、取出等操作时采用的复制机制。复制机制需要用到复制构造函数和赋值运算符重载。stl的复制机制是影响其性能的重要因素;
(2)在存在继承机制的关系时,拷贝动作会导致剥离。
措施:
不是建立对象的容器,而是建立对象指针的容器。


第4条:调用empty而不是检查size()是否为0

c.size()==0和c.empty()本质上是等价的,但是推荐使用empty()判断容器是否为空。原因是,对于任何容器,empty()的复杂度都是常数时间,但是对于list的size操作,可能是线性时间。因为list是链式存储的。考虑下面的例子:
list<int> list1; 
list<int> list2; 
... 
list1.splice(                   // 把list2中
    list1.end(), list2,         // 从第一次出现5到
    find(list2.begin(), list2.end(), 5),        // 最后一次出现10
    find(list2.rbegin(), list2.rend(), 10).base()   // 的所有节点移到list1的结尾。
);                      // 关于调用的
                        // "base()"的信息,请参见条款28


splice的时间复杂度取决于list的设置。这个函数的基本功能是将另外一个链表序列接到当前序列的尾部,如果要知道现在序列的长度,需要遍历一遍(线性时间)链表。
如果list的设置是:size()为常数时间,那么splice操作在完成基本功能的同时还要做线性时间的遍历操作。如果list的size()是线性时间,那么splice函数不用承担这个责任。
不管如何,size()的复杂度可能是线性的或常数的,empty一定是常数时间。

第5条:区间成员函数优先于预支对应的单元素成员函数

第6条:当心C++编译器最烦人的分析机制

第7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉

条款8:永不建立auto_ptr的容器
条款9:在删除选项中仔细选择
条款10:注意分配器的协定和约束
条款11:理解自定义分配器的正确用法
条款12:对STL容器线程安全性的期待现实一些


vector和string
条款13:尽量使用vector和string来代替动态分配的数组
条款14:使用reserve来避免不必要的重新分配
条款15:小心string实现的多样性
条款16:如何将vector和string的数据传给传统的API
条款17:使用“交换技巧”来修整过剩容量
条款18:避免使用vector<bool>
关联容器
条款19:了解相等和等价的区别
条款20:为指针的关联容器指定比较类型
条款21:永远让比较函数对相等的值返回false
条款22:避免原地修改set和multiset的键
条款23:考虑使用有序vector代替关联容器
条款24:当关乎效率时应该在map::operator[]和map-insert之间仔细选择
条款25:熟悉非标准散列容器
迭代器
条款26:尽量用iterator代替const_iterator,reverse_iterator和const_reverse_iterator
条款27:用distance和advance把const_iterator转化成iterator
条款28:了解如何通过reverse_iterator的base得到iterator
条款29:需要一个一个字符输入时考虑使用istreambuf_iterator
算法
条款30:确保目标区间足够大
条款31:了解你的排序选择
条款32:如果你真的想删除东西的话就在类似remove的算法后接上erase
条款33:提防在指针的容器上使用类似remove的算法
条款34:注意哪个算法需要有序区间
条款35:通过mismatch或lexicographical比较实现简单的忽略大小写字符串比较
条款36:了解copy_if的正确实现
条款37:用accumulate或for_each来统计区间
仿函数、仿函数类、函数等
条款38:把仿函数类设计为用于值传递
条款39:用纯函数做判断式
条款40:使仿函数类可适配
条款41:了解使用ptr_fun、mem_fun和mem_fun_ref的原因
条款42:确定less<T>表示operator<.
使用STL编程
条款43:尽量用算法调用代替手写循环
条款44:尽量用成员函数代替同名的算法
条款45:注意count、find、binary_search、lower_bound、upper_bound和equal_range的区别
条款46:考虑使用函数对象代替函数作算法的参数
条款47:避免产生只写代码
条款48:总是#include适当的头文件
条款49:学习破解有关STL的编译器诊断信息
条款50:让你自己熟悉有关STL的网站
参考书目
附录A:区域设置和忽略大小写的字符串比较
附录B:在微软STL平台上的注意事项
词汇表
索引

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值