C++STL
标准模板库
容器
- 容器:是一种可存储和管理对象集合的数据结构,直接实现了基本的数据存储和访问机制。例如,
vector是动态数组,list是双向链表,set是有序集合,unordered_map是哈希表形式的键值对集合。 它们各自按照不同的数据结构原理,来组织和存储元素。 - 容器适配器:是对已有的容器进行封装,改变其接口以满足特定的需求,本质上是一种包装器。它并不重新实现数据存储和管理机制,而是依赖于其他容器来完成这些工作。常见的容器适配器有
stack(栈)、queue(队列)、priority_queue(优先队列)。
容器:
flowchart TD
G{"*指向元素的指针或迭代器,无论添加或删除元素,始终有效<br>**双向链接"}
subgraph 序列容器
H{动态大小}
H -- 否 --> array
H -- 是 --> I{保持有序吗?}
I -- 否 --> J{是否在中间插入/删除元素?}
J -- 是 --> K{频繁遍历吗?}
J -- 否 --> L{是否在前端插入/删除元素?}
K -- 是 --> M{位置是否持久*?}
K -- 否 --> N{大小变化大吗?}
L -- 是 --> deque
L -- 否 --> vector
M -- 是 --> llist**
N -- 否 --> vector
N -- 是 --> llist**
end
subgraph 有序容器
I -- 是 --> O{主要用途?}
O -- 中序遍历 --> P[vector<sorted> 或 flat_set]
O -- 按键搜索 --> Q{允许重复元素吗?}
Q -- 否 --> R{键映射到值吗?}
Q -- 是 --> S{键映射到值吗?}
R -- 是 --> map
R -- 否 --> set
S -- 是 --> multimap
S -- 否 --> multiset
end
容器适配器:
flowchart TD
subgraph 自适应容器
A{顺序是否重要?}
A -- 是 --> B{后进先出}
A -- 否 --> C{先进先出}
B -- 是 --> stack
C -- 是 --> queue
C -- 否 --> priority_queue
end
subgraph 无序容器
D{允许重复元素吗?}
A -- 否 --> D
D -- 否 --> E{键映射到值吗?}
D -- 是 --> F{键映射到值吗?}
E -- 是 --> unordered_map
E -- 否 --> unordered_set
F -- 是 --> unordered_multimap
F -- 否 --> unordered_multiset
end
注意点
对于vector,emplace_back有更好的性能,应当优先使用.
string_view在没有需要修改字符串的情况下,比如string更好
迭代器
const迭代器
简单说,const_iterator 是一种 "只读" 的迭代器,它指向的数据不能被修改。就像你只能看一个东西,但不能碰它。而普通的 iterator 是 "可写" 的,既能看也能改。
-
防止意外修改数据(编译器会报错)
-
让代码意图更清晰(别人一看就知道这里不会修改数据)
以前(C++98)这个 const_iterator 不好用,主要问题是:
- 不容易创建(想从普通容器里拿到它很麻烦)
- 很多操作不支持(比如想在找到的位置插入数据,C++98 不接受用
const_iterator作为位置参数)
所以那时候大家宁可用普通 iterator,就算其实不需要修改数据。
从 C++11 开始,这些问题都解决了:
- 容器新增了
cbegin()、cend()方法,直接就能拿到const_iterator - 插入、删除等操作也支持用 const_iterator 来指定位置了
比如原来的代码可以改成这样(更简单且安全):
// 用 cbegin()/cend() 得到 const_iterator
auto it = std::find(values.cbegin(), values.cend(), 1983);
values.insert(it, 1998); // 现在可以直接用 const_iterator 了
C++11 还有个小遗憾:对于一些特殊的数据结构(比如原生数组),没有提供全局的 cbegin()、cend() 函数。C++14 补上了这个漏洞,让代码可以更通用。
总之:
- 写代码时,只要不需要修改迭代器指向的数据,就优先用
const_iterator - 获取迭代器时,优先用
cbegin()、cend()(而不是普通的begin()、end()) - 在通用代码中,优先用全局的
begin()、end()、cbegin()等函数(而不是容器的成员函数)
这样做能让代码更安全、更清晰、更通用。

浙公网安备 33010602011771号