揭开使用STL时各 陷阱的 来源 / 解决方案的优劣
接口与实现分离: 对于STL, 不能简单地使用这条规则
原因: STL实现的 通用&特殊性
关联容器: 有更多陷阱
6大部件
函数对象: 增强算法的 扩展性
STL库
(1) 是1个模板库
[1] 编译器
对于模板的支持
各不相同 => 可移植性
问题
[2] 小用法错误, 导致大量编译器诊断信息 -> 简化 -> 错误提示清晰
(2) 代表了 效率和扩展性
程序设计突破
引言
1 本书
(1)
讲如何 综合STL各个部分, 以充分利用STL库的设计
这可以帮助我们 为简单而直接/复杂的问题设计出简单而直接/优雅 的解决方案
(2) 指出常见STL用法错误, 如何避免
2 定义、使用和扩展STL
本书对STL的定义 不包括标准C++库的扩展部分
, 尤其是 散列容器、单向链表、rope, 非标准函数对象
STL平台: 一个
特定编译器
和一个特定STL实现
的组合引用计数(RC: reference count)
指针容器
设计 几乎都会用到 RC
很多 string 实现
也使用 RC
- string 和 wstring 是同一个模板 basic_string 的不同实例
本文所说的适用于string的内容也适用于wstring
- 术语
(1) 容器
标准序列/关联容器
vector string deque list /
set multiset map multimap
(2) 5种迭代器
[1/2] inputIter/outputIter
只读/写
遍历到的位置上只能被读/写一次
输入/出迭代器模型
分别建立在
针对输入/出流(如文件)的读/写操作
的基础上
最常见
的表现形式是 istream_iterator/ostream_iterator
[3] 前向
1] 兼具输入和输出迭代器的能力
2] 可对同一位置 重复读/写
所有标准STL容器
都支持比前向迭代器功能更强大的迭代器
散列容器
的一种设计(25条)产生 前向迭代器
单向链表容器
提供前向迭代器
[4] 双向
标准关联容器
都提供
[5] 随机
迭代器算术
string vector deque
都提供
数组内部指针之于数组
(3) functor 函数子/仿函数
重载了函数调用操作符 operator()(.)
的类
其创建的对象称 函数对象
STL中 大多使用函数对象的地方也可以使用函数
, 所以常用 函数对象 既表示 函数, 也表示 函数对象
(4) bind1st bind2nd
绑定器/binder
(5) 计算复杂性
保证
STL革命性的方面
限制了一个STL操作可以做多少工作
n: 容器/区间中 元素个数
[1] 常数时间
插入 list
非字面上的常数, 只意味 所需时间不受n的影响
变种: 分摊的常数时间
通常是常数时间, 偶尔花费与n相关
[2] 对数时间
一百万个元素是百个元素耗时的三倍
log n^3=3 logn
关联容器 大多数查找算法(如 set::find)
[3] 线性时间
对所给区间中的每个元素都要 check
count
n足够大时 常数时间快于对数时间快于线性时间
较小的n, 有时理论上更复杂的操作反而会比理论上更简单的操作性能更好
- map或multimap
每个元素有两部分 key 和 value
- 代码例子
(1) 从属类型 typename
(2) 参数名: lhs/rhs
左手一边”和“右手一边”
(3) 类名 Widget
与GUI / 具体的工具箱 没任何关系
指 “完成某些功能的某个类”
(4) 不会引起混淆时, 不区分类和类模板/ 函数和函数模板
与效率相关的条款-虚设的章节
item4 用 empty()而非 size()=0
item5 区间成员函数 优先于相应的 单元素成员函数
item14 用 reserve() 避免不必要的重新分配
item15 注意 string 实现的多样性
item23 考虑用 排序的vector 代替关联容器
item24 效率至关重要时, 要在map::operator[] 间 map::insert 正确选择
item25 熟悉 非标准散列容器
item29 逐字符输入考虑 istreambuf_iterator
item31 排序选择
item44 容器的成员函数 优先于同名算法
item46 算法参数考虑函数对象而非函数
Note 本书条款只是指导原则, 有一定的使用条件
有些条件下, 违反它们也是合理的
如 item7: 容器析构前要delete 容器中new的指针
前提: 指针指向的对象不再需要
时才这样
STL容器
动态增/缩
自己管理内存
记住自己包含了多少对象
限定了
自己所支持的操作的复杂性
本章讲 适用于所有STL容器的准则
[1] 如何就所面临的制约条件 选容器类型
[2] 避免一种错误认识: 同一代码可用于不同容器
[3] 对容器中的对象, copy 操作
的重要性
[4] 指针/auto_ptr 容器
的困难
[5] 删除
操作细节
[6] 定制的分配子
能做什么不能做什么
[7] 多线程下使用容器