C++ SLTL编程

C++ STL 编程完全指南

从入门到实践 · 含完整代码示例

2026年5月

目录

[1. STL 概述](#1. STL 概述)

[2. 容器(Containers)](#2. 容器(Containers))

[2.1 顺序容器](#2.1 顺序容器)

[2.2 关联容器](#2.2 关联容器)

[2.3 无序容器](#2.3 无序容器)

[2.4 容器适配器](#2.4 容器适配器)

[3. 迭代器(Iterators)](#3. 迭代器(Iterators))

[3.1 迭代器分类](#3.1 迭代器分类)

[3.2 迭代器操作](#3.2 迭代器操作)

[4. 算法(Algorithms)](#4. 算法(Algorithms))

[4.1 非修改算法](#4.1 非修改算法)

[4.2 修改算法](#4.2 修改算法)

[4.3 排序与查找](#4.3 排序与查找)

[5. 函数对象与 Lambda](#5. 函数对象与 Lambda)

[6. 字符串(string)](#6. 字符串(string))

[7. 综合实战案例](#7. 综合实战案例)

[8. 常见错误与最佳实践](#8. 常见错误与最佳实践)

1. STL 概述

STL(Standard Template Library,标准模板库)是 C++ 标准库的核心组成部分,由 Alexander Stepanov 设计,于 1994 年被纳入 C++ 标准。STL 以泛型编程(Generic Programming)为核心思想,通过模板(Template)机制实现了高度可复用的数据结构与算法。

STL 由三大核心组件构成:

  • 容器(Containers):存储数据的数据结构,如 vector、list、map 等。
  • 迭代器(Iterators):连接容器与算法的桥梁,提供统一的遍历接口。
  • 算法(Algorithms):对容器中数据进行操作的函数模板,如排序、查找、变换等。

💡 提示: 使用 STL 前需包含对应头文件,如 #include <vector>、#include <algorithm> 等。

1.1 STL 的优势

优势 说明
高效性 底层实现经过高度优化,时间复杂度有保证
通用性 基于模板,支持任意数据类型
可扩展性 可自定义分配器、比较器等
标准化 跨平台、跨编译器一致行为
代码复用 避免重复造轮子,减少 Bug

2. 容器(Containers)

容器是 STL 的基础,用于存储和管理数据。根据内部结构和使用场景,STL 容器分为四大类:

类别 代表容器 底层结构
顺序容器 vector / list / deque / array 数组 / 链表 / 双端队列
关联容器 map / set / multimap / multiset 红黑树(有序)
无序容器 unordered_map / unordered_set 哈希表
容器适配器 stack / queue / priority_queue 基于其他容器封装

2.1 顺序容器

2.1.1 vector --- 动态数组

vector 是最常用的顺序容器,底层为连续内存数组,支持随机访问,尾部插入/删除效率为 O(1),中间插入/删除为 O(n)。

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

int main() {

// 1. 创建与初始化

vector<int> v1; // 空 vector

vector<int> v2(5, 0); // 5 个 0

vector<int> v3 = {1, 2, 3, 4, 5}; // 初始化列表

vector<int> v4(v3.begin(), v3.end()); // 从迭代器构造

// 2. 添加元素

v1.push_back(10); // 尾部追加

v1.push_back(20);

v1.emplace_back(30); // 原地构造,比 push_back 更高效

// 3. 访问元素

cout << v30 << endl; // 下标访问(不检查越界)

cout << v3.at(1) << endl; // at() 访问(越界抛异常)

cout << v3.front() << endl; // 第一个元素

cout << v3.back() << endl; // 最后一个元素

// 4. 遍历

for (int x : v3) cout << x << " "; // 范围 for

cout << endl;

for (auto it = v3.begin(); it != v3.end(); ++it)

cout << *it << " "; // 迭代器遍历

cout << endl;

// 5. 插入与删除

v3.insert(v3.begin() + 2, 99); // 在索引 2 处插入 99

v3.erase(v3.begin() + 2); // 删除索引 2 处元素

v3.pop_back(); // 删除最后一个元素

// 6. 容量管理

cout << "size: " << v3.size() << endl; // 元素个数

cout << "capacity: " << v3.capacity() << endl; // 已分配容量

v3.reserve(100); // 预分配 100 个元素的空间

v3.shrink_to_fit(); // 释放多余容量

v3.clear(); // 清空所有元素

// 7. 排序

vector<int> nums = {5, 2, 8, 1, 9, 3};

sort(nums.begin(), nums.end()); // 升序

sort(nums.begin(), nums.end(), greater<int>()); // 降序

for (int x : nums) cout << x << " ";

return 0;

}

💡 提示: reserve() 可避免频繁扩容导致的内存重分配,当预知元素数量时应提前调用。

2.1.2 list --- 双向链表

list 底层为双向链表,任意位置插入/删除为 O(1),但不支持随机访问(无 \[\] 运算符)。适合频繁插入删除的场景。

#include <list>

int main() {

list<int> lst = {3, 1, 4, 1, 5, 9, 2, 6};

// 头尾操作

lst.push_front(0); // 头部插入

lst.push_back(7); // 尾部插入

lst.pop_front(); // 删除头部

lst.pop_back(); // 删除尾部

// 在迭代器位置插入

auto it = lst.begin();

advance(it, 2); // 移动迭代器到第 3 个位置

lst.insert(it, 100); // 在该位置前插入 100

// 删除特定值

lst.remove(1); // 删除所有值为 1 的元素

// 排序(list 有自己的 sort,不能用 std::sort)

lst.sort(); // 升序排序

lst.sort(greater<int>()); // 降序排序

// 去重(需先排序)

lst.unique(); // 删除相邻重复元素

// 合并两个有序 list

list<int> lst2 = {2, 4, 6};

lst.merge(lst2); // lst2 合并到 lst,lst2 变为空

for (int x : lst) cout << x << " ";

return 0;

}

2.1.3 deque --- 双端队列

deque(double-ended queue)支持在头部和尾部高效插入/删除(O(1)),同时支持随机访问。底层由多个固定大小的内存块组成。

#include <deque>

int main() {

deque<int> dq = {3, 4, 5};

dq.push_front(2); // 头部插入

dq.push_front(1);

dq.push_back(6); // 尾部插入

cout << dq0 << endl; // 随机访问,输出 1

cout << dq.at(2) << endl; // 输出 3

dq.pop_front(); // 删除头部

dq.pop_back(); // 删除尾部

for (int x : dq) cout << x << " "; // 2 3 4 5

return 0;

}

2.1.4 array --- 固定大小数组

array 是对 C 风格数组的封装,大小在编译期确定,不可动态扩容,但提供了 STL 风格的接口。

#include <array>

int main() {

array<int, 5> arr = {1, 2, 3, 4, 5};

cout << arr.size() << endl; // 5

cout << arr.front() << endl; // 1

cout << arr.back() << endl; // 5

cout << arr2 << endl; // 3

// 支持 STL 算法

sort(arr.begin(), arr.end(), greater<int>());

for (auto x : arr) cout << x << " "; // 5 4 3 2 1

return 0;

}

2.2 关联容器

关联容器基于红黑树实现,元素自动有序,查找/插入/删除时间复杂度均为 O(log n)。

2.2.1 map --- 键值对映射

map 存储 key-value 对,key 唯一且自动升序排列。

#include <map>

#include <string>

int main() {

map<string, int> scores;

// 插入元素(三种方式)

scores"Alice" = 95; // 下标赋值

scores.insert({"Bob", 87}); // insert + 初始化列表

scores.emplace("Charlie", 92); // emplace 原地构造

// 访问

cout << scores"Alice" << endl; // 95

cout << scores.at("Bob") << endl; // 87(不存在则抛异常)

// 查找

auto it = scores.find("Charlie");

if (it != scores.end())

cout << it->first << ": " << it->second << endl;

// 判断 key 是否存在

if (scores.count("Dave") == 0)

cout << "Dave not found" << endl;

// 遍历(按 key 升序)

for (auto& key, val : scores) // C++17 结构化绑定

cout << key << " -> " << val << endl;

// 删除

scores.erase("Bob");

scores.erase(scores.begin()); // 删除第一个元素

cout << "size: " << scores.size() << endl;

return 0;

}

💡 提示: scores"key" 若 key 不存在会自动插入默认值(0),建议用 find() 或 count() 先判断。

2.2.2 set --- 唯一元素集合

set 存储唯一元素,自动升序排列,常用于去重和有序集合操作。

#include <set>

int main() {

set<int> s = {5, 3, 1, 4, 1, 5, 9}; // 重复元素自动去除

// s 内容: {1, 3, 4, 5, 9}

s.insert(2); // 插入 2

s.erase(3); // 删除 3

// 查找

if (s.find(4) != s.end())

cout << "4 exists" << endl;

// 范围查找

auto lo = s.lower_bound(3); // 第一个 >= 3 的迭代器

auto hi = s.upper_bound(7); // 第一个 > 7 的迭代器

for (auto it = lo; it != hi; ++it)

cout << *it << " "; // 4 5

// 遍历

for (int x : s) cout << x << " "; // 1 2 4 5 9

return 0;

}

2.2.3 multimap 与 multiset

multimap 允许重复 key,multiset 允许重复元素,其余行为与 map/set 相同。

#include <map>

#include <set>

int main() {

// multimap: 同一 key 可对应多个 value

multimap<string, int> mm;

mm.insert({"math", 90});

mm.insert({"math", 85});

mm.insert({"english", 78});

// 获取某 key 的所有值

auto range = mm.equal_range("math");

for (auto it = range.first; it != range.second; ++it)

cout << it->second << " "; // 90 85

// multiset: 允许重复元素

multiset<int> ms = {1, 2, 2, 3, 3, 3};

cout << ms.count(3) << endl; // 3(值为 3 的元素个数)

ms.erase(2); // 删除所有值为 2 的元素

for (int x : ms) cout << x << " "; // 1 3 3 3

return 0;

}

2.3 无序容器(哈希容器)

无序容器基于哈希表实现,平均查找/插入/删除时间复杂度为 O(1),但元素无序。适合对性能要求高、不需要有序的场景。

2.3.1 unordered_map

#include <unordered_map>

#include <string>

int main() {

unordered_map<string, int> umap;

// 插入

umap"apple" = 3;

umap"banana" = 5;

umap.emplace("cherry", 2);

// 访问与查找

cout << umap"apple" << endl; // 3

if (umap.count("banana"))

cout << "banana: " << umap"banana" << endl;

// 遍历(顺序不确定)

for (auto& k, v : umap)

cout << k << "=" << v << " ";

// 性能参数

cout << "bucket_count: " << umap.bucket_count() << endl;

cout << "load_factor: " << umap.load_factor() << endl;

umap.reserve(100); // 预分配桶数量,减少 rehash

return 0;

}

2.3.2 unordered_set

#include <unordered_set>

int main() {

unordered_set<int> us = {3, 1, 4, 1, 5, 9, 2, 6};

// 重复的 1 自动去除,顺序不确定

us.insert(7);

us.erase(3);

if (us.find(5) != us.end())

cout << "5 found" << endl;

cout << "size: " << us.size() << endl;

return 0;

}

容器 有序 vs 无序 / 时间复杂度
map / set 有序(红黑树),O(log n)
unordered_map / unordered_set 无序(哈希表),平均 O(1)
适用场景 需要有序用 map/set;追求速度用 unordered_*

2.4 容器适配器

容器适配器是对底层容器的封装,提供特定的访问接口,限制了部分操作以满足特定数据结构语义。

2.4.1 stack --- 栈(LIFO)

#include <stack>

int main() {

stack<int> st;

st.push(1); // 入栈

st.push(2);

st.push(3);

cout << st.top() << endl; // 3(查看栈顶,不弹出)

cout << st.size() << endl; // 3

while (!st.empty()) {

cout << st.top() << " "; // 3 2 1

st.pop(); // 弹出栈顶

}

return 0;

}

2.4.2 queue --- 队列(FIFO)

#include <queue>

int main() {

queue<int> q;

q.push(1); // 入队

q.push(2);

q.push(3);

cout << q.front() << endl; // 1(队头)

cout << q.back() << endl; // 3(队尾)

while (!q.empty()) {

cout << q.front() << " "; // 1 2 3

q.pop(); // 出队

}

return 0;

}

2.4.3 priority_queue --- 优先队列(堆)

priority_queue 默认为最大堆(堆顶为最大值),可通过比较器改为最小堆。

#include <queue>

#include <vector>

#include <functional>

int main() {

// 最大堆(默认)

priority_queue<int> maxHeap;

maxHeap.push(3);

maxHeap.push(1);

maxHeap.push(4);

maxHeap.push(1);

maxHeap.push(5);

while (!maxHeap.empty()) {

cout << maxHeap.top() << " "; // 5 4 3 1 1

maxHeap.pop();

}

cout << endl;

// 最小堆

priority_queue<int, vector<int>, greater<int>> minHeap;

minHeap.push(3);

minHeap.push(1);

minHeap.push(4);

minHeap.push(1);

minHeap.push(5);

while (!minHeap.empty()) {

cout << minHeap.top() << " "; // 1 1 3 4 5

minHeap.pop();

}

return 0;

}

3. 迭代器(Iterators)

迭代器是 STL 的核心抽象,提供了一种统一的方式来遍历不同类型的容器,使算法与容器解耦。迭代器的行为类似于指针。

3.1 迭代器分类

类型 支持操作 代表容器
输入迭代器(Input) 单向读取,只能前进 istream_iterator
输出迭代器(Output) 单向写入,只能前进 ostream_iterator
前向迭代器(Forward) 单向读写,可多次遍历 forward_list
双向迭代器(Bidirectional) 双向读写(++ 和 --) list, map, set
随机访问迭代器(Random Access) 支持 +n、-n、\[\] vector, deque, array

3.2 迭代器操作详解

#include <vector>

#include <list>

#include <iterator>

#include <algorithm>

int main() {

vector<int> v = {1, 2, 3, 4, 5};

// ── 基本迭代器操作 ──

auto it = v.begin(); // 指向第一个元素

auto end = v.end(); // 指向最后一个元素的下一位

cout << *it << endl; // 解引用,输出 1

++it; // 前进

cout << *it << endl; // 输出 2

it += 2; // 随机访问迭代器可跳跃

cout << *it << endl; // 输出 4

// ── 反向迭代器 ──

for (auto rit = v.rbegin(); rit != v.rend(); ++rit)

cout << *rit << " "; // 5 4 3 2 1

cout << endl;

// ── const 迭代器(只读)──

for (auto cit = v.cbegin(); cit != v.cend(); ++cit)

cout << *cit << " "; // 不能通过 cit 修改元素

cout << endl;

// ── advance 与 distance ──

auto it2 = v.begin();

advance(it2, 3); // 移动 3 步,指向 v3=4

cout << *it2 << endl; // 4

cout << distance(v.begin(), it2) << endl; // 3

// ── next 与 prev ──

auto it3 = next(v.begin(), 2); // 返回 begin+2 的迭代器

auto it4 = prev(v.end(), 1); // 返回 end-1 的迭代器

cout << *it3 << " " << *it4 << endl; // 3 5

// ── 插入迭代器 ──

vector<int> dest;

copy(v.begin(), v.end(), back_inserter(dest)); // 尾部插入

copy(v.begin(), v.end(), front_inserter(dest)); // 头部插入(需 deque/list)

// ── 流迭代器 ──

// 从标准输入读取整数到 vector

// vector<int> input_v(istream_iterator<int>(cin), istream_iterator<int>());

// 输出到标准输出

copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

return 0;

}

4. 算法(Algorithms)

STL 提供了超过 100 个算法函数模板,定义在 <algorithm> 和 <numeric> 头文件中。所有算法通过迭代器操作容器,与容器类型无关。

4.1 非修改算法

非修改算法不改变容器内容,只进行查找、统计、比较等操作。

#include <algorithm>

#include <vector>

#include <numeric>

int main() {

vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};

// find --- 查找第一个匹配元素

auto it = find(v.begin(), v.end(), 5);

if (it != v.end())

cout << "found 5 at index: " << distance(v.begin(), it) << endl; // 4

// find_if --- 按条件查找

auto it2 = find_if(v.begin(), v.end(), \[\](int x){ return x > 7; });

cout << "first > 7: " << *it2 << endl; // 9

// count --- 统计元素个数

cout << "count(1): " << count(v.begin(), v.end(), 1) << endl; // 2

// count_if --- 按条件统计

int even_cnt = count_if(v.begin(), v.end(), \[\](int x){ return x % 2 == 0; });

cout << "even count: " << even_cnt << endl; // 3

// all_of / any_of / none_of

cout << all_of(v.begin(), v.end(), \[\](int x){ return x > 0; }) << endl; // 1(true)

cout << any_of(v.begin(), v.end(), \[\](int x){ return x > 8; }) << endl; // 1(true)

cout << none_of(v.begin(), v.end(), \[\](int x){ return x < 0; }) << endl; // 1(true)

// min_element / max_element

auto minIt = min_element(v.begin(), v.end());

auto maxIt = max_element(v.begin(), v.end());

cout << "min=" << *minIt << " max=" << *maxIt << endl; // min=1 max=9

// accumulate --- 求和(在 <numeric> 中)

int sum = accumulate(v.begin(), v.end(), 0);

cout << "sum: " << sum << endl; // 39

// accumulate 自定义操作(求乘积)

int product = accumulate(v.begin(), v.begin()+4, 1, multiplies<int>());

cout << "product of first 4: " << product << endl; // 12

return 0;

}

4.2 修改算法

修改算法会改变容器中的元素值或结构。

#include <algorithm>

#include <vector>

int main() {

vector<int> v = {1, 2, 3, 4, 5};

vector<int> dest(5);

// copy --- 复制

copy(v.begin(), v.end(), dest.begin());

// dest: {1, 2, 3, 4, 5}

// fill --- 填充

fill(dest.begin(), dest.end(), 0);

// dest: {0, 0, 0, 0, 0}

// generate --- 用函数生成值

int n = 0;

generate(v.begin(), v.end(), \&n{ return n++ * 2; });

// v: {0, 2, 4, 6, 8}

// transform --- 变换每个元素

vector<int> v2 = {1, 2, 3, 4, 5};

vector<int> result(5);

transform(v2.begin(), v2.end(), result.begin(),

\[\](int x){ return x * x; }); // 平方

// result: {1, 4, 9, 16, 25}

// transform 双范围版本(两个容器对应元素相加)

vector<int> a = {1,2,3}, b = {10,20,30}, c(3);

transform(a.begin(), a.end(), b.begin(), c.begin(), plus<int>());

// c: {11, 22, 33}

// replace --- 替换特定值

vector<int> v3 = {1, 2, 3, 2, 1};

replace(v3.begin(), v3.end(), 2, 99);

// v3: {1, 99, 3, 99, 1}

// replace_if --- 按条件替换

replace_if(v3.begin(), v3.end(), \[\](int x){ return x > 50; }, 0);

// v3: {1, 0, 3, 0, 1}

// remove + erase 惯用法(erase-remove idiom)

vector<int> v4 = {1, 2, 3, 2, 4, 2, 5};

v4.erase(remove(v4.begin(), v4.end(), 2), v4.end());

// v4: {1, 3, 4, 5}

// unique + erase(去除相邻重复,需先排序)

vector<int> v5 = {1,1,2,3,3,3,4,5,5};

v5.erase(unique(v5.begin(), v5.end()), v5.end());

// v5: {1, 2, 3, 4, 5}

// reverse --- 反转

vector<int> v6 = {1, 2, 3, 4, 5};

reverse(v6.begin(), v6.end());

// v6: {5, 4, 3, 2, 1}

// rotate --- 旋转

vector<int> v7 = {1, 2, 3, 4, 5};

rotate(v7.begin(), v7.begin() + 2, v7.end());

// v7: {3, 4, 5, 1, 2}(以第3个元素为新起点)

return 0;

}

4.3 排序与查找算法

#include <algorithm>

#include <vector>

#include <string>

int main() {

vector<int> v = {5, 2, 8, 1, 9, 3, 7, 4, 6};

// ── 排序 ──

sort(v.begin(), v.end()); // 升序

sort(v.begin(), v.end(), greater<int>()); // 降序

sort(v.begin(), v.end(), \[\](int a, int b){ // 自定义比较

return a % 3 < b % 3; // 按模3余数排序

});

// stable_sort --- 稳定排序(相等元素保持原相对顺序)

vector<pair<int,string>> ps = {{2,"b"},{1,"a"},{2,"c"},{1,"d"}};

stable_sort(ps.begin(), ps.end(),

\[\](auto& a, auto& b){ return a.first < b.first; });

// 结果: {1,a},{1,d},{2,b},{2,c} 相同 key 保持原顺序

// partial_sort --- 部分排序(只排前 k 个)

vector<int> v2 = {5, 2, 8, 1, 9, 3};

partial_sort(v2.begin(), v2.begin()+3, v2.end());

// 前3个有序: {1, 2, 3, ...}

// nth_element --- 第 n 小的元素归位

vector<int> v3 = {5, 2, 8, 1, 9, 3};

nth_element(v3.begin(), v3.begin()+2, v3.end());

cout << "3rd smallest: " << v32 << endl; // 3

// ── 二分查找(需先排序)──

vector<int> sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// binary_search --- 判断是否存在

cout << binary_search(sorted.begin(), sorted.end(), 5) << endl; // 1

// lower_bound --- 第一个 >= target 的位置

auto lb = lower_bound(sorted.begin(), sorted.end(), 5);

cout << "lower_bound(5): index " << distance(sorted.begin(), lb) << endl; // 4

// upper_bound --- 第一个 > target 的位置

auto ub = upper_bound(sorted.begin(), sorted.end(), 5);

cout << "upper_bound(5): index " << distance(sorted.begin(), ub) << endl; // 5

// equal_range --- 返回 [lower_bound, upper_bound) 对

vector<int> v4 = {1,2,2,2,3,4};

auto lo, hi = equal_range(v4.begin(), v4.end(), 2);

cout << "count of 2: " << distance(lo, hi) << endl; // 3

// ── 排列 ──

vector<int> perm = {1, 2, 3};

do {

for (int x : perm) cout << x << " ";

cout << endl;

} while (next_permutation(perm.begin(), perm.end()));

// 输出 {1,2,3} 的全部 6 种排列

return 0;

}

5. 函数对象与 Lambda 表达式

函数对象(Functor)和 Lambda 表达式是 STL 算法的重要配套工具,用于自定义算法的行为。

5.1 内置函数对象(<functional>)

STL 在 <functional> 中提供了一系列内置函数对象:

函数对象 等价操作 示例
plus<T> a + b accumulate(v.begin(),v.end(),0,plus<int>())
minus<T> a - b transform(...)
multiplies<T> a * b accumulate(...,1,multiplies<int>())
divides<T> a / b transform(...)
modulus<T> a % b transform(...)
negate<T> -a transform(...)
equal_to<T> a == b find_if(...)
less<T> a < b sort(...,less<int>())
greater<T> a > b sort(...,greater<int>())
logical_and<T> a && b all_of(...)
logical_or<T> a || b any_of(...)

5.2 自定义函数对象

#include <algorithm>

#include <vector>

#include <functional>

// 自定义函数对象:判断是否能被 n 整除

struct DivisibleBy {

int n;

DivisibleBy(int n) : n(n) {}

bool operator()(int x) const { return x % n == 0; }

};

// 自定义比较器:按绝对值排序

struct AbsCompare {

bool operator()(int a, int b) const {

return abs(a) < abs(b);

}

};

int main() {

vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 使用自定义函数对象

int cnt = count_if(v.begin(), v.end(), DivisibleBy(3));

cout << "divisible by 3: " << cnt << endl; // 3

vector<int> v2 = {-5, 3, -1, 4, -2};

sort(v2.begin(), v2.end(), AbsCompare());

// v2: {-1, -2, 3, 4, -5}

return 0;

}

5.3 Lambda 表达式(C++11 起)

Lambda 是匿名函数,语法为:捕获列表(参数列表) -> 返回类型 { 函数体 }

#include <algorithm>

#include <vector>

#include <functional>

int main() {

// ── 基本 Lambda ──

auto add = \[\](int a, int b) -> int { return a + b; };

cout << add(3, 4) << endl; // 7

// ── 捕获外部变量 ──

int threshold = 5;

vector<int> v = {1, 3, 5, 7, 9, 2, 4, 6, 8};

// = 值捕获(拷贝)

auto gt = =(int x){ return x > threshold; };

int cnt = count_if(v.begin(), v.end(), gt);

cout << "count > 5: " << cnt << endl; // 4

// \& 引用捕获(可修改外部变量)

int sum = 0;

for_each(v.begin(), v.end(), \&sum(int x){ sum += x; });

cout << "sum: " << sum << endl; // 45

// threshold 只捕获特定变量

auto between = threshold(int x){ return x > threshold && x < threshold + 4; };

cnt = count_if(v.begin(), v.end(), between);

cout << "between 5 and 9: " << cnt << endl;

// ── mutable Lambda(修改值捕获的变量)──

int counter = 0;

auto inc = counter() mutable { return ++counter; };

cout << inc() << " " << inc() << " " << inc() << endl; // 1 2 3

cout << "original counter: " << counter << endl; // 0(未改变)

// ── 在 STL 算法中使用 Lambda ──

vector<string> words = {"banana", "apple", "cherry", "date"};

sort(words.begin(), words.end(),

\[\](const string& a, const string& b){ return a.size() < b.size(); });

// 按字符串长度排序: date apple banana cherry

// ── std::function 存储 Lambda ──

function<int(int,int)> multiply = \[\](int a, int b){ return a * b; };

cout << multiply(6, 7) << endl; // 42

return 0;

}

6. 字符串(std::string)

std::string 是 STL 提供的字符串类,封装了 C 风格字符串,提供了丰富的操作接口,是 C++ 中处理文本的标准方式。

#include <string>

#include <sstream>

#include <algorithm>

int main() {

// ── 创建与初始化 ──

string s1 = "Hello, World!";

string s2(5, 'A'); // "AAAAA"

string s3 = s1.substr(0, 5); // "Hello"

// ── 基本操作 ──

cout << s1.length() << endl; // 13

cout << s1.size() << endl; // 13(同 length)

cout << s1.empty() << endl; // 0(false)

cout << s10 << endl; // H

cout << s1.at(1) << endl; // e

cout << s1.front() << endl; // H

cout << s1.back() << endl; // !

// ── 拼接 ──

string s4 = s3 + " STL"; // "Hello STL"

s4 += "!"; // "Hello STL!"

s4.append(" Great"); // "Hello STL! Great"

// ── 查找 ──

string text = "the quick brown fox jumps over the lazy dog";

size_t pos = text.find("fox");

if (pos != string::npos)

cout << "fox at: " << pos << endl; // 16

pos = text.rfind("the"); // 从后往前找

cout << "last the at: " << pos << endl; // 31

pos = text.find_first_of("aeiou"); // 第一个元音字母

cout << "first vowel at: " << pos << endl; // 2

// ── 替换与修改 ──

string s5 = "Hello World";

s5.replace(6, 5, "STL"); // 从位置6替换5个字符

cout << s5 << endl; // "Hello STL"

s5.insert(5, " Beautiful"); // 在位置5插入

cout << s5 << endl; // "Hello Beautiful STL"

s5.erase(5, 10); // 从位置5删除10个字符

cout << s5 << endl; // "Hello STL"

// ── 大小写转换 ──

string s6 = "Hello World";

transform(s6.begin(), s6.end(), s6.begin(), ::toupper);

cout << s6 << endl; // "HELLO WORLD"

transform(s6.begin(), s6.end(), s6.begin(), ::tolower);

cout << s6 << endl; // "hello world"

// ── 数字与字符串互转 ──

int num = 42;

string numStr = to_string(num); // int -> string

int back = stoi(numStr); // string -> int

double d = stod("3.14"); // string -> double

cout << numStr << " " << back << " " << d << endl;

// ── stringstream 分割字符串 ──

string csv = "apple,banana,cherry,date";

stringstream ss(csv);

string token;

vector<string> tokens;

while (getline(ss, token, ','))

tokens.push_back(token);

for (auto& t : tokens) cout << t << " ";

// apple banana cherry date

// ── 比较 ──

string a = "apple", b = "banana";

cout << (a < b) << endl; // 1(字典序)

cout << (a == b) << endl; // 0

cout << a.compare(b) << endl; // 负数(a < b)

return 0;

}

7. 综合实战案例

以下通过几个完整的实战案例,展示 STL 各组件的综合运用。

7.1 单词频率统计

使用 map 统计文本中每个单词出现的频率,并按频率降序输出 Top-N。

#include <iostream>

#include <map>

#include <vector>

#include <string>

#include <sstream>

#include <algorithm>

using namespace std;

int main() {

string text = "the quick brown fox jumps over the lazy dog "

"the fox was quick and the dog was lazy";

// 1. 统计词频

map<string, int> freq;

stringstream ss(text);

string word;

while (ss >> word) freqword++;

// 2. 转为 vector<pair> 以便排序

vector<pair<string,int>> vec(freq.begin(), freq.end());

// 3. 按频率降序排序

sort(vec.begin(), vec.end(),

\[\](auto& a, auto& b){ return a.second > b.second; });

// 4. 输出 Top-5

cout << "Top-5 words:" << endl;

for (int i = 0; i < min(5, (int)vec.size()); i++)

cout << veci.first << ": " << veci.second << endl;

// the: 4

// fox: 2

// lazy: 2

// quick: 2

// dog: 2

return 0;

}

7.2 学生成绩管理系统

综合运用 vector、map、sort、算法等实现一个简单的学生成绩管理系统。

#include <iostream>

#include <vector>

#include <map>

#include <algorithm>

#include <numeric>

#include <string>

using namespace std;

struct Student {

string name;

map<string, int> scores; // 科目 -> 分数

double average() const {

if (scores.empty()) return 0;

int total = accumulate(scores.begin(), scores.end(), 0,

\[\](int sum, auto& p){ return sum + p.second; });

return (double)total / scores.size();

}

};

int main() {

vector<Student> students = {

{"Alice", {{"Math",95},{"English",88},{"Science",92}}},

{"Bob", {{"Math",78},{"English",85},{"Science",80}}},

{"Charlie", {{"Math",90},{"English",76},{"Science",88}}},

{"Diana", {{"Math",88},{"English",92},{"Science",95}}},

};

// 按平均分降序排序

sort(students.begin(), students.end(),

\[\](auto& a, auto& b){ return a.average() > b.average(); });

// 输出排名

cout << "=== 成绩排名 ===" << endl;

for (int i = 0; i < (int)students.size(); i++) {

cout << i+1 << ". " << studentsi.name

<< " 平均分: " << studentsi.average() << endl;

}

// 找出数学最高分

auto best = max_element(students.begin(), students.end(),

\[\](auto& a, auto& b){

return a.scores.at("Math") < b.scores.at("Math");

});

cout << "数学最高分: " << best->name

<< " (" << best->scores.at("Math") << ")" << endl;

// 统计平均分 >= 88 的学生

int honor = count_if(students.begin(), students.end(),

\[\](auto& s){ return s.average() >= 88; });

cout << "优秀学生数: " << honor << endl;

return 0;

}

7.3 图的邻接表表示(BFS)

使用 unordered_map + vector 表示图,并用 queue 实现广度优先搜索(BFS)。

#include <iostream>

#include <unordered_map>

#include <vector>

#include <queue>

#include <unordered_set>

using namespace std;

// 邻接表图

using Graph = unordered_map<int, vector<int>>;

void addEdge(Graph& g, int u, int v) {

gu.push_back(v);

gv.push_back(u); // 无向图

}

vector<int> bfs(const Graph& g, int start) {

vector<int> order;

unordered_set<int> visited;

queue<int> q;

q.push(start);

visited.insert(start);

while (!q.empty()) {

int node = q.front(); q.pop();

order.push_back(node);

if (g.count(node)) {

for (int neighbor : g.at(node)) {

if (!visited.count(neighbor)) {

visited.insert(neighbor);

q.push(neighbor);

}

}

}

}

return order;

}

int main() {

Graph g;

addEdge(g, 1, 2); addEdge(g, 1, 3);

addEdge(g, 2, 4); addEdge(g, 2, 5);

addEdge(g, 3, 6);

auto result = bfs(g, 1);

cout << "BFS order: ";

for (int x : result) cout << x << " ";

// 1 2 3 4 5 6

return 0;

}

8. 常见错误与最佳实践

8.1 常见错误

错误 1:迭代器失效

在遍历容器时修改容器(插入/删除),会导致迭代器失效,引发未定义行为。

// ❌ 错误:遍历 vector 时删除元素

vector<int> v = {1, 2, 3, 4, 5};

for (auto it = v.begin(); it != v.end(); ++it) {

if (*it % 2 == 0) v.erase(it); // 迭代器失效!

}

// ✅ 正确:erase 返回下一个有效迭代器

for (auto it = v.begin(); it != v.end(); ) {

if (*it % 2 == 0) it = v.erase(it);

else ++it;

}

// ✅ 更简洁:erase-remove 惯用法

v.erase(remove_if(v.begin(), v.end(), \[\](int x){ return x%2==0; }), v.end());

错误 2:map 的 \[\] 运算符副作用

// ❌ 错误:用 \[\] 检查 key 是否存在会插入默认值

map<string,int> m;

if (m"key" == 0) { /* key 不存在,但已被插入!*/ }

// ✅ 正确:用 count() 或 find()

if (m.count("key") == 0) { /* key 不存在 */ }

if (m.find("key") == m.end()) { /* key 不存在 */ }

错误 3:vector 越界访问

vector<int> v = {1, 2, 3};

// ❌ 错误:\[\] 不检查越界,行为未定义

cout << v5 << endl;

// ✅ 正确:at() 越界时抛出 std::out_of_range 异常

try {

cout << v.at(5) << endl;

} catch (const out_of_range& e) {

cout << "Out of range: " << e.what() << endl;

}

错误 4:对未排序容器使用二分查找

vector<int> v = {5, 3, 1, 4, 2};

// ❌ 错误:binary_search 要求容器已排序

bool found = binary_search(v.begin(), v.end(), 3); // 结果不可靠

// ✅ 正确:先排序再查找

sort(v.begin(), v.end());

found = binary_search(v.begin(), v.end(), 3); // true

8.2 最佳实践

  • 优先使用范围 for 循环:for (auto& x : container) 比手写迭代器更简洁安全。
  • 使用 emplace 代替 push:emplace_back() 原地构造,避免拷贝,性能更好。
  • 预分配 vector 容量:已知元素数量时调用 reserve(),避免频繁扩容。
  • 选择合适的容器:频繁随机访问用 vector;频繁头尾操作用 deque;频繁中间插删用 list;键值查找用 map/unordered_map。
  • 使用 auto 简化类型:auto it = m.find(key) 比 map<string,int>::iterator it 更简洁。
  • 使用 const 引用遍历:for (const auto& x : v) 避免不必要的拷贝。
  • erase-remove 惯用法:删除满足条件的元素时,使用 v.erase(remove_if(...), v.end())。
  • 结构化绑定(C++17):for (auto& key, val : map) 比 it->first/it->second 更清晰。

8.3 容器选择速查表

需求 推荐容器 原因
随机访问 + 尾部增删 vector 连续内存,O(1) 随机访问
头尾频繁增删 deque 两端 O(1) 操作
任意位置频繁增删 list 链表,O(1) 插删
有序键值映射 map 红黑树,O(log n)
快速键值映射 unordered_map 哈希表,O(1) 平均
有序唯一集合 set 红黑树,自动排序
快速唯一集合 unordered_set 哈希表,O(1) 平均
LIFO 栈 stack 基于 deque 封装
FIFO 队列 queue 基于 deque 封装
优先级队列 priority_queue 基于 vector 的堆
固定大小数组 array 编译期大小,零开销

--- 文档结束 ---

相关推荐
许彰午6 小时前
14_Java泛型完全指南
java·windows·python
智慧物业老杨7 小时前
司法绿色通道下的物业纠纷数智化解决方案——基于“三优先“机制的全流程技术落地实践
java·django
2601_961194027 小时前
2026初级会计实务公式总结大全|计算题公式手册PDF
java·spring·eclipse·pdf·tomcat·hibernate
做个文艺程序员7 小时前
第1篇:K8s 核心概念精讲:Pod、Deployment、Service 与 Namespace——Java 开发者快速上手指南
java·云原生·容器·kubernetes·容器编排
小欣加油9 小时前
leetcode3751 范围内总波动值I
java·数据结构·c++·算法·leetcode
代码中介商9 小时前
C++左值与右值:核心判断法则详解
开发语言·c++
闪电悠米9 小时前
黑马点评-Redisson-01_why_redisson
java·服务器·网络·数据库·缓存·wpf
星轨zb9 小时前
LangChain4j 集成 Spring Boot:会话记忆 NPE 的根源与 ChatMemoryProvider 正确配置
java·spring boot·后端·langchain4j
JAVA9659 小时前
JAVA面试-并发篇 05-并发包AQS队列实现原理是什么
java·开发语言·面试
JAVA面经实录9179 小时前
RocketMQ全套学习知识手册
java·kafka·rabbitmq·rocketmq