最近有闲,在工作之余重读了《effective STL》一书,并通过 twitter 记了一下笔记,今天整理收集到这里。
twitter 真的非常适合记读书笔记,哈哈,以后要好好地发扬。另,我的手机还是很老的 UIQ 3.0 的索爱手机,有没有达人推荐一些上推的应用程序?谢谢。
====================================
#estl 第50条:熟悉与STL相关的web站点。三个:www.sgi.com/tech/stl、www.stlport.org 和 www.boost.org。
#estl 第49条:学会分析与STL相关的编译器诊断信息。嗯,第一招是替换大法,然后介绍了一下与容器、插入迭代器、绑定器、输出迭代器或算法相关的错误大概有什么套路看。
#estl 第48条:总是包含(#include)正确 的头文件。因为C++标准没有规定头文件的互相包含关系,所以不同的STL实现有所不同。要记住容器基本上声明在同名文件中,算法是algo..和 num..,迭代器在iterator中,函数子和配接器在functional中。
#estl 第47条:避免产生“直写型”(write-only)的代码。即所谓容易编写,但难以阅读和理解的代码,比如一行调用函数12次,其中 10 个是互不相同的。
#estl 第46条:考虑使用函数对象而不是函数作为STL算法的参数。嗯,因为函数对象更容易让编译器乐于内联,所以速度会快一些。从代码被编译器接受的程度而言,它们更加稳定可靠。
#estl 第45条:正确区分count、find、binary_search、lower_bound、upper_bound和equal_range。嗯,这与传入的区间是否已经排序有关,与你的目的有关,与容器有关,总之复杂,要自己去看这一小节两次。
googollee 我一直认为这个应该由重载来完成 RT @laiyonghao: #estl 第44条:容器的成员函数优先于同名的算法。原因:速度更快,且与容器结合得更加紧密,更能够与容器的行为保持一致。
#estl 第44条:容器的成员函数优先于同名的算法。原因:速度更快,且与容器结合得更加紧密,更能够与容器的行为保持一致。
#estl 第43条:算法调用优先于手写的循环。三个理由:效率更高,更不容易出错,和更好的可维护性。
#estl 第42条:确保less<T>与operator<T>具有相同的语义。真理总是如此平淡……还能说啥呢?
#estl 第41条:理解ptr_fun、mem_fun和mem_fun_ref的来由。咳,想起当年理解 .* 和 ->* 的时候多么地头痛……
#estl 第40条:若一个类是函数子,则应使它可配接。因为 STL 的函数配接器要求一些特殊的类型定义,argument_type,result_type...之类。编写函数子从unary_function或 binary_function继承是一个不错的方案。
#estl 第39条:确保判别式是“纯函数”。纯函数即返回值仅仅依赖于其参数的函数。估计在这条阴沟里翻过船的人不少,哈哈哈。
#estl 第38条:遵循按值传递的原则来设计函数子类。换句话说就是让它们小巧,而且单态。这个条款的意义在于为赘重而且多态的函数子带来的问题提出一个解决方案,pimpl 惯用法。
#estl 第37条:使用accumulate或者for_each进行区间统计,前者的代码更明了一些,重要的是它们接受的函数子要求不同。
#estl 第36条:理解copy_if算法的正确实现。文中给出了一个正确实现,注意点是不能要求使用的函数子是可配接的,STL 算法都这样。
#estl 第35条:通过mismatch或lexicographical_compare实现简单的忽略大小写的字符串比较。
#estl 第34条:了解哪此算法要求使用排序的区间作为参数。嗯,STL 算法有不少是要排序的区间的,如果实参并非如此,轻则性能下降,重则逻辑错误,不可不察。
#estl 第33条:对包含指针的容器使用remove这一类算法时要特别小心。作为cpp程序员,一定要时刻警惕资源泄漏。boost::shared_ptr是一个好选择。
#estl 第32条:如果确实需要删除元素,则需要在remove这一类算法之后调用erase。嗯,讲的就是erase-remove惯用法的由来,另外在讲了一次不同容器删除元素的方法是不同的。
#estl 第31条:了解各种与排序有关的选择。简言之,介绍了partition/stable_partition/nth_element /partial_sort/sort/stable_sort的用法和适用场合。
吼吼,到这里,书就看了一半了。接下来是重头戏:算法。 #estl 第30条:确保目标区间足够大。特别是做覆盖的时候,一定要注意,可以先用resize撑大。插入时用back_inserter、front_...、 inserter和ostream_iterator。
#estl 第29条:对于逐个字符的输入请考虑使用istreambuf_iterator。先说了一下istream_iterator会跳过空白符的问题,然后引入...buf...,后者的性能也会更好,嗯,例子里的string使用了区间构造函数,又一个推荐的惯用法。
#estl 第28条:正确理解由reverse_itrator的base()成员函数所产生的iterator用法。简言之就是base()返回的迭代器有偏移,插入和删除操作的时候要注意。再介绍了一个v.erase((++ri).base())惯用法。
#estl 第27条:使用distance和advance将容器的const_iterator转换成iterator。其实这是前一条的延伸,讲述了相应的转换方法和要注意的地方,比如显式指定distance的类型参数为const_...,以避免编译器推断。
周末在家继续看了一点点书,补推上来。 #estl 第26条:iterator优先于const_iterator、reverse_...以及const_reverse...。因为 insert/erase等函数需要,以及彼此间的比较,还有就是iterator更能灵活转换。
#estl 第25条:熟悉非标准的哈希容器。嗯,这些玩意儿是非标准的,C++0x 出来以后就会有标准了……
RT @googollee: 用vector的好处是内存布局可控,可直接导给c api。应该是vector性能不行了才用关联容器 RT @laiyonghao #estl 第23条:考虑用排序的vector替代关联容器。……//维护一个sorted_vector代价挺大的。
#estl 第24条:当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择。简言之,增加时使用insert,更新时使用[]。
#estl 第23条:考虑用排序的vector替代关联容器。额,我觉得除非证明了关联容器性能不行了,不然不应该考虑。map 不行了用 hashmap。
#estl 第22条:切勿直接修改set或multiset中的键。关键是要记住如果直接修改了,那么要保证该容器仍然是排序的。对python之类的语言其实也是如此。
#estl 第21条:总是让比较函数在等值情况下返回false。听起来像废话?嗯,重要的是要记得 !(a<b) 的意思是 a>=b,切记要把前者写成 b<a 形式。 回复 回推
#estl 第20条:为包含指针的关联容器指定比较类型。这条已经约定成俗了,没什么好说的。
#estl 第19条:理解相等(equality)和等价(equivalence)的区别。相等,以 operator== 为基础,等价,以 operator< 为基础,当 !(a<b)&&!(b<a) 时两者等价。
#estl 读完第2章,再感叹一下温故知新。另外 twitter 真是做读书笔记的好工具。
#estl 第18条:避免使用vector<bool>。这条也是金规玉律了,无需多言。
#estl 第17条:使用“swap技巧”去除多余的容量。这条太常用了,没啥好说的。
#estl 第16条:了解如何把 vector和string数据传给旧的API。嗯,再一次觉得&v[0]实在太恶心了。因为只有vector才保证和数组有同样的内存布局,所以如果要把map之类的容器内容传给C-API,可能需要vector中转一下。
#estl 第15条:注意string实现的多样性。谈到了四个不同的实现,并分析了他们占用的内存大小,引用和共享能力。非常有趣。
#estl 第14条:使用reserve来避免不必要的重新分配。先分析了vector/string的内存策略和相关的方法,然后谈到reserve惯用法。
#estl 第13条:vector和string优先于动态分配的数组。主要因为它们的内存管理和各种嵌套类型定义方便编程,另外讨论到基于引用计数的string 可能在多线程环境中损失性能。
重看 #estl 已经看完第一章了,我不得不说 C++ 的书是会中毒的,我现在变得有很强的欲望去重看 ecpp 和 mecpp 了……我好不容易通过写py三年修来的金身马上要破了……
#estl 第12条:切勿对STL容器的线程安全性有不切实际的依赖。只能期望(不可依赖哦)多线程读是安全的,多个线程对不同的容器做写入操作是安全的。
#estl 又读了一遍第10条。第11条:理解自定义分配子的合理用法。
#estl 第10条:了解分配子(allocator)的约定和限制。果然温故知新,这一条耗了我好几个编译代码的时间……可能仍然需要再重读几遍,鹅米豆腐……
#estl 第8条:切勿创建包含auto_ptr的容器对象;第9条:慎重选择删除元素的方法。关键点:auto_ptr在拷贝时转移所有权;序列容器和关联容器的删除方法不一样,list尤其特别。
RT @googollee: 第7条看情况吧,如果容器里的东西在容器销毁后还需要继续存在的话就不能delete。ecpp是embedded cpp么? RT @laiyonghao: #ecpp 第7条…… // 我用错tag了,effective stl,以后改 #estl
#ecpp 第7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉;第8条:切勿创建包含auto_ptr的容器对象。
#ecpp 第6条:当心C++编译器最烦人的分析机制。意思大概是在函数调用时避免使用匿名对象作实参,以消除对编译器的二义性。
#ecpp 第5条:区间成员函数优先于与之对应的单元素成员函数。区间成员函数写起来更容易,更能清楚地表达你的意图,而且它们表现出了更高的效率。
#ecpp 第3条:确保容器中的对象拷贝正确而高效;第4条:调用 empty 而不是检查 size() 是否为 0。
重读《Effective STL 中文版》。第1条:慎重选择容器类型;第2条:不要试图编写独立于容器类型的代码