C++ 开发手册C++

CHAPTER 03表达层 · STL

STL 标准库

容器、迭代器、算法、string 与 vector/map/unordered_map。用标准库表达算法,少造轮子、多复用久经考验的实现。

开始阅读难度中级先修第一、二章约3小时
03.1

容器概览

顺序容器(vector/deque/list)、关联容器(map/set,红黑树)、无序容器(unordered_map,哈希)、容器适配器(stack/queue/priority_queue)。

容器底层典型复杂度适用
vector连续数组随机访问 O(1),尾部插入均摊 O(1)默认首选
map红黑树插入/查找 O(log n),有序需有序键
unordered_map哈希表平均 O(1)快速查找
03.2

vector

vector 是默认首选容器:连续内存、缓存友好、支持随机访问。用 emplace_back 原地构造避免多余拷贝。

std::vector<int> v;
v.push_back(1);
v.emplace_back(2);             // 原地构造,更优
v.reserve(100);                // 预分配,避免多次扩容
for (size_t i = 0; i < v.size(); ++i) { }
知道大小就用 reserve

在已知元素数量时调用 reserve 避免反复重新分配与拷贝,是常见性能优化点。

03.3

关联容器

map 存键值对(按 key 有序),set 存唯一键。插入用 emplace,查找用 find 或 contains(C++20)。

std::map<std::string, int> scores;
scores.emplace("Alice", 90);
if (auto it = scores.find("Alice"); it != scores.end())
  std::cout << it->second;
03.4

迭代器

迭代器是连接容器与算法的"胶水":begin/end 界定范围,算法通过迭代器操作元素,与容器解耦。

for (auto it = v.begin(); it != v.end(); ++it) {
  std::cout << *it;
}
范围 for 的底层

范围 for 本质就是迭代器遍历,写起来更简洁。需要下标时用索引,需要修改用 auto&。

03.5

算法

STL 算法(sort、find、count、transform、accumulate 等)作用于迭代器范围,复用标准实现、可读且高效。

#include <algorithm>
std::sort(v.begin(), v.end());
int sum = std::accumulate(v.begin(), v.end(), 0);
auto n = std::count_if(v.begin(), v.end(),
                       [](int x){ return x > 0; });
03.6

string

std::string 是连续字符序列,自动管理内存,提供查找、拼接、子串等操作。

std::string s = "hello";
s += " world";
size_t pos = s.find("world");
std::string sub = s.substr(0, 5);   // "hello"
字符串视图

只读场景传 std::string_view 避免拷贝与分配;它不拥有内存,别让它指向已销毁的字符串。

03.7

适配器与工具

stack/queue/priority_queue 是容器适配器;std::array(定长、栈上)、std::span(C++20,连续序列视图)也很常用。

std::priority_queue<int> pq;   // 默认大顶堆
pq.push(3); pq.push(1);
int top = pq.top();             // 3
03.8

常见陷阱与 FAQ

迭代器失效是什么?

vector 插入/删除可能使已有迭代器、引用、指针失效(扩容或元素移动)。修改容器后不要再使用旧的迭代器,必要时用返回值刷新。

vector 还是 list?
绝大多数情况 vector 更快(缓存局部性)。list 只在频繁中部插入且元素很大、移动昂贵时考虑。

map 和 unordered_map 怎么选?

需要有序遍历或有范围查询用 map;只求极速单点查找用 unordered_map,但要注意哈希质量与最坏 O(n)。

03.9

实战练习与资源

延伸资源