effective STL

effective STL

五月 23, 2019 阅读 45 字数 2669 评论 0 喜欢 0

一.仔细选择你的容器

二.小心对容器无关的幻想.不要试图写下兼容所有容器类型的代码,当你可能想要换另一种容器的时候,就使用typedef去定义一个型别,在以后的代码中使用这个型别,类似于:typedef vector<Widget> WidgetContainer;包括定义一个它的迭代器类型,也可以为这个容器封装一个类,因为通常会伴随其他操作

三.使容器里对象的拷贝操作轻量而正确.不要拷贝容器元素型别的派生类,会发生对象切割,要想处理这种问题,可以存放对象指针,当然这也会有其他问题,所以建议存放智能指针

四.用empty来代替检查size()是否为0.empty是一个常数时间的操作,但对于一 些list实现,size花费线性时间,因为list有splice的成员函数,它并不知道插入的切片有多少元素,不能有类似于size的成员变量,list更重要的插入删除为常数时间,只能舍弃去计算splice时候的元素个数。

五.尽量使用区间成员函数代替它们的单元素兄弟.例如使用vector的assign而不是algorithm里的copy,因为它们的开销不一样,并且std::copy还要自己保证内存空间足够,BTW避免手写循环

六.警惕C++最令人恼怒的解析.class Widget {…}; Widget w(); 这只是一个函数声明,并非定义了一个w对象.

七.当使用new得指针的容器时,记得在销毁容器前delete那些指针.初级的做法:手写for循环来delete,进阶:写一个泛型的delete functor,放到std::for_each去释放.更好的做法:使用智能指针,但是不要愚蠢地去使用auto_ptr,正确的选择是使用share_ptr,下面这个例子的functor使用应该加上()的

八.永不建立auto_ptr的容器,因为auto_ptr发生拷贝时候,会使原来的失效,这个过时的东西就不要用它了,如果不允许使用C++11,那就尽量连auto_ptr都不要用吧,这样的公司也真是坑!

九.在删除选项中仔细选择.在关联式容器中删除元素的方法:写过n多demo了,迭代器自增的位置从for()的位置移动到{}内.在序列式容器中:迭代器会全部失效,但是erase会返回下个迭代器的位置,所以在{}中,是iterator=erase().在序列式容器中,还有一种惯用的操作:erase-remove手法,如:

v.erase(std::remove(v.begin(), v.end(), val),v.end())

std::remove()使用后,容器的size不会发生变化,值为val的元素会被放在后面,再调用erase删除remove返回的迭代器到end()

std::unique和std::remove_if也是一样

.

.

.

…写了n久,没保存成功,算了继续写吧,反正基本不会来看这写的,中间也就一些trick而已,比如map的[]和insert的差别,Wedget w();会被当做是一个函数声明之类的…

二十七.用distance和advance把const_iterator转化成iterator

advance(i, distance<const_iterator>(i, ci));

二十八.了解如何通过reverse_iterator的base得到iterator

二十九.需要一个一个字符输入时考虑使用istreambuf_iterator,什么年代了…算了,还是了解下原因吧,是因为istreambuf读的是缓存,istream_iterator读的是文件

条款30:确保目标区间足够大.

std::copy (bar.rbegin(),bar.rend(),std::front_inserter(foo));

transform(values.begin(), values.end(), back_inserter(results),transmogrify);

std的算法要求用户自几去保证空间足够,inserter在iterator这个类里,会调用对应的insert函数 

条款31:了解你的排序选择

条款32:如果你真的想删除东西的话就在类似remove的算法后接上 erase

条款33:提防在指针的容器上使用类似remove的算法

条款34:注意哪个算法需要有序区间

条款35:通过mismatch或lexicographical比较实现简单的忽略大小写字 符串比较

条款36:了解copy_if的正确实现

条款37:用accumulate或for_each来统计区间

条款38:把仿函数类设计为用于值传递.使用桥模式实现functor的多态,值得一看

条款39:用纯函数做判断式.operator()必须是const,它也不应该去改变参数

条款40:使仿函数类可适配

条款41:了解使用ptr_fun、mem_fun和mem_fun_ref的原因.什么年代了…现在都用std::bind了…

条款42:确定less<T>表示operator<

条款43:尽量用算法调用代替手写循环

● 效率:算法通常比程序员产生的循环更高效。 ● 正确性:写循环时比调用算法更容易产生错误。 ● 可维护性:算法通常使代码比相应的显式循环更干净、更直观。

算法的设计者更清楚容器内部细节,比如判断是否等于end(),自己写的循环每次迭代都要获取一遍,而算法只需要一次;使用原生指针移动要比迭代器更快,手写循环一般用不了容器内部的原生指针

条款44:尽量用成员函数代替同名的算法

条款45:注意count、find、binary_search、lower_bound、upper_bound 和equal_range的区别.后四者要求有序,时间是对数级,前两者不要求顺序,时间为线性.在实际运用方面,我过多地使用find(其实场景是用的大多都是容器自带的find,也不算滥用),忽略lower_bound,upper_bound,binary_search,equal_range的使用,对他们的正确运用参照下图:

条款46:考虑使用函数对象代替函数作算法的参数.因为functor的操作符重载会inline,没有使用纯函数时产生的函数调用的开销(这些开销被转移到编译期去了).比如c++的sort会比c的qsort快670%…

条款47:避免产生只写代码.确保维护性

条款48:总是#include适当的头文件

条款49:学习破解有关STL的编译器诊断信息

条款50:让你自己熟悉有关STL的网站

发表评论

电子邮件地址不会被公开。