Effective STL — 50条有效使用STL的经验
作者: Scott Meyers
云盘路径: /books/c++/effective c++/Effective STL.pdf
文件大小: 2.06MB
页数: 200页
处理日期: 2026-09-03
处理方法: pdf-inspector文本提取
核心要点
Scott Meyers的”Effective”系列第三部,继《Effective C++》和《More Effective C++》之后,专注STL最佳实践。全书50条Item,涵盖容器选择、迭代器、算法、函数对象四大主题。
章节结构与核心Item
一、容器(Containers)— Item 1-12
Item 1: 谨慎选择容器
- 区分连续内存容器(vector, string, deque)与节点容器(list, set, map)
- 选择容器时考虑:随机访问需求、排序需求、标准兼容性、迭代器类型、元素移动成本、C布局兼容、查找速度、引用计数、事务语义、迭代器失效规则
- 没有”默认容器”,vector不是万能的
Item 2: 警惕容器无关代码的幻觉
- 不同容器有本质差异(迭代器类型、失效规则、性能特征)
- 试图写通用容器代码会丧失几乎所有优势
- 用typedef封装而非抽象化,便于未来替换
Item 3: 容器中的对象拷贝要廉价且正确
- 容器存的是拷贝而非原件(copy in, copy out)
- 继承体系中存入基类容器会导致slicing
- 解决方案:存指针(配合智能指针)
Item 4: 用empty()代替size()==0
- empty()对所有标准容器都是O(1)
- 某些list实现的size()是O(n)
Item 5: 优先使用范围成员函数
assign, range insert, range erase比单元素版本更高效- 减少函数调用开销、减少元素移动次数、减少内存重分配
Item 6: 警惕C++最烦人的解析
Widget w();声明的是返回Widget的函数,不是对象- 用括号包裹参数可强制解析为对象构造
Item 7: 容器存newed指针时记得delete
- 容器析构不delete指针
- 用for_each+DeleteObject函子或智能指针
Item 8: 永远不要创建auto_ptr容器
- auto_ptr拷贝时转移所有权,破坏容器不变量
- 排序可能将元素设为NULL
- C++标准禁止auto_ptr容器
Item 9: 谨慎选择擦除选项
- vector/deque/string: erase-remove惯用法
- list: list::remove/remove_if
- 关联容器: erase成员函数
- 自定义擦除时注意迭代器失效规则
Item 10: 了解分配器的约定与限制
- allocator::pointer/reference typedef常被实现忽略
- 同类型分配器被认为总是相等
- 不同容器不能共享分配器
Item 11: 理解自定义分配器的合法用途
- 检测错误、收集统计、共享内存、空间优化
- 大多数情况不需要自定义分配器
Item 12: 对STL容器的线程安全保持现实期望
- 只读并发是安全的
- 写入并发需要外部同步
- 同一容器不允许读写并发
二、vector与string — Item 13-18
Item 13: 优先使用vector和string代替动态数组
- 自动内存管理、size跟踪、复制语义
- 动态数组无法传递size信息
Item 14: 用reserve避免不必要的重新分配
- vector自动倍增容量(通常×2)
- reserve可减少重分配次数
Item 15: 了解string实现的变体
- 大多数实现使用引用计数(Copy-on-Write)
- 引用计数导致const correctness问题
- vector
可替代string避免此问题
Item 16: 将vector和string数据传递给遗留API
- vector数据连续存储,可用
&v[0]传递 - string数据连续存储,但C++98不保证(C++11保证)
Item 17: 用swap技巧修剪多余容量
- vector无shrink_to_fit
- 用swap临时vector可释放多余容量
Item 18: 避免使用vector
- 不是真正的容器(特殊化)
- 不返回bool&,返回代理对象
- 用bitset或vector
替代
三、关联容器 — Item 19-25
Item 19: 理解相等性与等价性的区别
- 相等性:ab且ba
- 等价性:!comp(a,b) && !comp(b,a)
- 关联容器使用等价性判断
Item 20: 为指针关联容器指定比较类型
- map<int*>默认按指针值排序而非所指对象
- 需提供自定义比较器
Item 21: 比较函数对相等值必须返回false
- 违反此规则导致未定义行为
Item 22: 避免在set/multiset中就地修改键
- 修改键破坏容器排序不变量
- 应erase后重新insert
Item 23: 考虑用排序vector替代关联容器
- 内存效率更高
- 迭代器失效更少
- 二分搜索性能相当
Item 24: 效率敏感时谨慎选择map::operator[]与insert
- operator[]在找不到时会插入默认值
- insert不会改变容器
Item 25: 熟悉非标准哈希容器
- hash_set/hash_map等提供O(1)查找
- 非标准但广泛可用
- SGI STLport Boost提供实现
四、迭代器 — Item 26-29
Item 26: 优先使用iterator而非const_iterator等
- 类型推导困难
- 代码更简洁
Item 27: 用distance和advance转换const_iterator
- 将const_iterator转为iterator的标准做法
Item 28: 理解reverse_iterator的base迭代器
- base()返回的是”下一个”位置
- 用于关联容器erase时有陷阱
Item 29: 考虑用istreambuf_iterator逐字符输入
- 绕过locale转换,效率更高
五、算法 — Item 30-37
Item 30: 确保目标范围足够大
- back_inserter等插入迭代器可避免此问题
- 但语义不同,需小心
Item 31: 了解你的排序选项
- sort/stable_sort/partial_sort/nth_element适用场景
- 排序算法要求随机访问迭代器
Item 32: remove-like算法后接erase才能真正删除
- erase-remove惯用法
- remove不改变容器size
Item 33: 对指针容器警惕remove-like算法
- remove只移动指针不delete对象
- 需自定义删除逻辑
Item 34: 注意哪些算法要求排序范围
- binary_search/lower_bound/upper_bound/equal_range
- 未排序范围调用导致未定义行为
Item 35: 用mismatch或lexicographical_compare实现大小写不敏感比较
Item 36: 正确实现copy_if
- C++98无copy_if,需自定义
Item 37: 用accumulate或for_each汇总范围
- accumulate适合数值汇总
- for_each适合副作用操作
六、函数对象 — Item 38-42
Item 38: 设计按值传递的函数对象类
- 函数对象通常按值传递给算法
- 确保拷贝构造函数高效
Item 39: 谓词必须是纯函数
- 无副作用
- 相同输入产生相同输出
Item 40: 使函数对象类可适配
- 继承unary_function/binary_function
- 提供argument_type/result_type等typedef
Item 41: 理解ptr_fun/mem_fun/mem_fun_ref的用途
- 将函数指针/成员函数转为函数对象
- C++11后用bind/lambdas替代
Item 42: 确保less
- 关联容器默认使用less
- 自定义类型需重载operator<
七、STL编程 — Item 43-50
Item 43: 优先使用算法调用而非手写循环
- 更简洁、更少错误、可能被优化
Item 44: 优先使用成员函数而非同名算法
- list::sort比std::sort更高效(利用splice)
- deque无排序算法对应物
Item 45: 区分count/find/二分搜索/bound函数
- count: 统计相等元素数
- find: 线性查找
- binary_search: 判断是否存在
- lower_bound/upper_bound/equal_range: 定位范围
Item 46: 考虑用函数对象替代函数作为算法参数
- 函数对象可携带状态
- 可被内联优化
Item 47: 避免写出难以维护的代码
- 过度使用模板元编程
- 过度使用非标准扩展
Item 48: 始终包含正确的头文件
- C++标准头文件无扩展名
<vector>而非<vector.h>
Item 49: 学会解读STL相关编译器诊断
- 替换basic_string等冗长类型为简短别名
- 替换_tree等实现细节类型
Item 50: 熟悉STL相关网站
- SGI STL: http://www.sgi.com/tech/stl/
- STLport: http://www.stlport.org/
- Boost: http://www.boost.org/
与其他笔记的关联
- Effective-C++-中文版-42条指南 — C++编程基础
- Effective-Modern-C++-Scott-Meyers — C++11/14现代特性
- C++-Concurrency-in-Action-中文版-第361次运行 — 并发编程
- Modern-Cpp-Design-Andrei-Alexandrescu — 泛型编程设计