Effective STL读书笔记

没有c++程序不使用STL,这是一本讲述如何正确高效地使用STL的参考书。

STL的核心是容器和算法,有了一定的使用经验之后,本书可以作为技术提升的点睛之笔。

本书成文较早,技术已经发生了较大的变化,取其精华。

容器


  1. 慎重选择容器类型。
  • 标准STL序列容器:vector, string, deque, list。
  • 标准STL关联容器:set, multiset, map, multimap。
  • 非标准序列容器:slist, rope。
  • 非标准关联容器:hash_set, hash_multiset, hash_map, hash_multimap。
  • vector vs string
  • vector vs 标准关联容器
  • 标准的非STL容器:array, bitset, valarray, stack, queue, priority_queue
  1. 不要试图编写独立于容器类型的代码。
  2. 确保容器中的对象拷贝正确而高效。要注意无处不在的拷贝。
  3. 使用empty()而非size()来确认容器是否为空。不用纠结,安全而可靠。
  4. 区间成员函数优先于与之对应的单元素成员函数。如给vector赋值时,优先使用assign而非push_back。
  5. 当心编译器糟糕的分析机制。
  6. 如果容器中包含了通过new创建的指针,记得容器析构前将指针delete掉。使用智能指针后应该没有这个问题了。
  7. 绝对不要创建包含auto_ptr的容器对象。考虑到容器中无处不在的复制,当然不通使用auto_ptr这种词不达意的东西。当然,auto_ptr已经废弃了。
  8. 慎重选择删除元素的方法。erase-remove/remove_if/remove_copy_if && swap/erase。
  9. 了解分配子的约定和限制。
  10. 理解自定义分配子的合理用法。
  11. 切勿对STL容器的线程安全性有不切实际的依赖。
  • 多个线程读是安全的(没有写操作)。
  • 多个线程对不同容器做写入操作是安全的(一个容器不会被并发写)。

vector和string


  1. vector和string优先于动态分配的数组。
  2. 使用reserve避免不必要的内存重新分配。提前分配好足够使用的内存,分清楚size, capacity, resize和reserve的区别与联系。
  3. 注意string实现的多样性。
  4. 了解如何把vector和string数据传给旧的API接口。
  5. 使用swap技巧去除多余的容量。
  6. 不要使用vector。因为它的行为不是真的bool。

关联容器


  1. 理解相等与等价的区别。
  2. 为包含指针的关联容器指定比较类型。
  3. 总是让比较函数在等值的情况下返回false。
  4. 不要直接修改set和multiset中的键。因为它们是排序的,修改会打乱这一生态。
  5. 考虑使用排序的vector代替关联容器。这取决于具体的使用场合。
  6. 当效率至关重要时,慎重选择map::operator[]和map::insert。参考c++ map实用操作
  7. 熟悉非标准的hash容器。现在已经可以直接使用unordered_map了。

迭代器


  1. iterator优先于const_iterator/reverse_iterator/const_reverse_iterator。
  2. 使用distance/advance将容器的const_iterator转换为iterator。
  3. 正确理解由reverse_iterator的base()成员函数生成的iterator的用法。
  4. 对于逐个字符的输入考虑使用istreambuf_iterator。

算法


  1. 确保目标区间足够大。使用成员函数,如back_inserter,容器会自动扩充内存。
  2. 了解各种与排序有关的选择。sort/partial_sort/nth_element/stable_sort/partion/stable_partion,各有千秋。
  3. 如果确实要删除元素,在remove类算法之后调用erase。
  4. 对包含指针的容器使用remove算法时要特别小心。同样,使用智能指针吧。
  5. 了解要求使用排序区间作为参数的特定算法。

Effective STL读书笔记

  1. 通过mismatch/lexicographical_compare实现简单的忽略大小写的字符串比较。
  2. 理解copy_if算法的正确实现。
  3. 使用accumulate或者for_each进行区间统计。

函数子、函数子类、函数及其他


  1. 遵循按值传递的原则来设计函数子类。
  2. 确保判别式是纯函数。纯爷们,知道吧?
  3. 若一个类是函数子,则应使它可配接。
  4. 理解ptr_fun/mem_fun/mem_fun_ref的由来。
  5. 确保less与operator<具有相同的含义。

在程序中使用STL


  1. 算法调用优于手写循环。如果有手写的循环了,考虑一下是否有算法可替代。
  2. 容器的成员函数优于同名的算法。私人定制优于大锅饭。
  3. 正确区别count/find/binary_search/lower_bound/upper_bound/equal_bound。

Effective STL读书笔记

  1. 考虑使用函数对象而非函数作为STL算法的参数。
  2. 避免产生“直写型”代码。易读好懂的代码才是好代码。
  3. 不要忘记包含正确的头文件。
  4. 学会分析与STL相关的编译器诊断信息。
  5. 熟悉与STL相关的web站点。
参考资料

《Effective STL》