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 << v3[0] << 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 << dq[0] << 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 << arr[2] << 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 步,指向 v[3]=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\ a = {1,2,3}, b = {10,20,30}, c(3); transform(a.begin(), a.end(), b.begin(), c.begin(), plus\()); // c: {11, 22, 33} // replace --- 替换特定值 vector\ 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\ 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\ 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\ v6 = {1, 2, 3, 4, 5}; reverse(v6.begin(), v6.end()); // v6: {5, 4, 3, 2, 1} // rotate --- 旋转 vector\ 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 \ #include \ #include \ int main() { vector\ v = {5, 2, 8, 1, 9, 3, 7, 4, 6}; // ── 排序 ── sort(v.begin(), v.end()); // 升序 sort(v.begin(), v.end(), greater\()); // 降序 sort(v.begin(), v.end(), \[\](int a, int b){ // 自定义比较 return a % 3 \< b % 3; // 按模3余数排序 }); // stable_sort --- 稳定排序(相等元素保持原相对顺序) vector\\> 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\ v2 = {5, 2, 8, 1, 9, 3}; partial_sort(v2.begin(), v2.begin()+3, v2.end()); // 前3个有序: {1, 2, 3, ...} // nth_element --- 第 n 小的元素归位 vector\ v3 = {5, 2, 8, 1, 9, 3}; nth_element(v3.begin(), v3.begin()+2, v3.end()); cout \<\< "3rd smallest: " \<\< v3\[2\] \<\< endl; // 3 // ── 二分查找(需先排序)── vector\ 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\ 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\ 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 内置函数对象(\) STL 在 \ 中提供了一系列内置函数对象: | **函数对象** | **等价操作** | **示例** | |------------------|----------|-----------------------------------------------| | plus\ | a + b | accumulate(v.begin(),v.end(),0,plus\()) | | minus\ | a - b | transform(...) | | multiplies\ | a \* b | accumulate(...,1,multiplies\()) | | divides\ | a / b | transform(...) | | modulus\ | a % b | transform(...) | | negate\ | -a | transform(...) | | equal_to\ | a == b | find_if(...) | | less\ | a \< b | sort(...,less\()) | | greater\ | a \> b | sort(...,greater\()) | | logical_and\ | a \&\& b | all_of(...) | | logical_or\ | a \|\| b | any_of(...) | ### 5.2 自定义函数对象 #include \ #include \ #include \ // 自定义函数对象:判断是否能被 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\ 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\ 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 \ #include \ #include \ int main() { // ── 基本 Lambda ── auto add = \[\](int a, int b) -\> int { return a + b; }; cout \<\< add(3, 4) \<\< endl; // 7 // ── 捕获外部变量 ── int threshold = 5; vector\ 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\ 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\ 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 \ #include \ #include \ 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 \<\< s1\[0\] \<\< 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\ 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 \ #include \ #include \ #include \ #include \ #include \ 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\ freq; stringstream ss(text); string word; while (ss \>\> word) freq\[word\]++; // 2. 转为 vector\ 以便排序 vector\\> 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 \<\< vec\[i\].first \<\< ": " \<\< vec\[i\].second \<\< endl; // the: 4 // fox: 2 // lazy: 2 // quick: 2 // dog: 2 return 0; } ### 7.2 学生成绩管理系统 综合运用 vector、map、sort、算法等实现一个简单的学生成绩管理系统。 #include \ #include \ #include \ #include \ #include \ #include \ using namespace std; struct Student { string name; map\ 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\ 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 \<\< ". " \<\< students\[i\].name \<\< " 平均分: " \<\< students\[i\].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 \ #include \ #include \ #include \ #include \ using namespace std; // 邻接表图 using Graph = unordered_map\\>; void addEdge(Graph\& g, int u, int v) { g\[u\].push_back(v); g\[v\].push_back(u); // 无向图 } vector\ bfs(const Graph\& g, int start) { vector\ order; unordered_set\ visited; queue\ 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\ 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\ m; if (m\["key"\] == 0) { /\* key 不存在,但已被插入!\*/ } // ✅ 正确:用 count() 或 find() if (m.count("key") == 0) { /\* key 不存在 \*/ } if (m.find("key") == m.end()) { /\* key 不存在 \*/ } #### 错误 3:vector 越界访问 vector\ v = {1, 2, 3}; // ❌ 错误:\[\] 不检查越界,行为未定义 cout \<\< v\[5\] \<\< 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\ 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\::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 | 编译期大小,零开销 | *---* *文档结束 ---*

相关推荐
java修仙传1 小时前
Java 实习日记:从业务表关系到节点价格分析接口改造
java·开发语言·实习
qq_452396231 小时前
第十四篇:《JMeter插件扩展:自定义函数与第三方插件》
开发语言·python·jmeter
敲代码的嘎仔1 小时前
力扣高频SQL基础50题详解
开发语言·数据库·笔记·sql·算法·leetcode·后端开发
码农-阿杰1 小时前
Java 线程等待唤醒机制深度解析:synchronized、ReentrantLock、LockSupport 底层实现对比
java·开发语言·c++
赤水无泪1 小时前
Qt 全模块汇总列表
开发语言·qt
yong99901 小时前
MATLAB仿真计算电磁波回波信号的技术路径与实现指南
开发语言·matlab
数字化顾问1 小时前
(122页PPT)企业数字化IT架构蓝图规划设计方案(附下载方式)
java·运维·架构
不是光头 强1 小时前
Spring Boot 多线程场景下 i18n 国际化失效问题排查与解决
java·开发语言·springboot
jieyucx1 小时前
Go 语言核心关键字:defer 深度解析与实战避坑
开发语言·后端·golang·defer