跳到主要内容
C++ STL 基础讲解 | 极客日志
C++ 算法
C++ STL 基础讲解 综述由AI生成 C++ STL 的五大核心组件:容器、算法、迭代器、仿函数和适配器。容器负责数据存储,如 vector、list 等;算法提供通用操作方法,如排序、查找;迭代器作为桥梁连接容器与算法;仿函数实现可携带状态的函数对象;适配器用于转换接口。文章详细阐述了各组件的分类、特性及协同工作流程,并通过示例展示了如何使用 STL 进行数据管理和处理,强调了组件间的松耦合设计思想。
活在当下 发布于 2026/3/26 更新于 2026/5/29 27 浏览一、STL 总体架构
STL 是 C++ 标准库的核心组成部分。它不是单一的概念,而是由五个相互协作的组件组成的完整体系。这五个组件就像一个精密的钟表,每个部件都有自己的职责,协同工作。
想象一下这五个组件的关系:
容器 是各种盒子 (书架、衣柜、抽屉)
算法 是操作方法 (怎么放、怎么取、怎么整理)
迭代器 是手或工具 (连接你和盒子的桥梁)
仿函数 是智能工具 (带特殊功能的夹子、剪刀)
适配器 是转换接口 (把方孔变成圆孔的转接头)
二、五大组件详解
1. 容器(Containers)—— 数据的'盒子'
容器就是装数据的各种'容器' ,就像现实中的数组、链表、树、哈希表等数据结构的模板实现。
1.1 容器分类(三层理解)
第一层:按存储方式分
序列容器 :元素按线性顺序排列
vector:动态数组(像可以自动扩容的货架)
deque:双端队列(像两头的传送带)
list:双向链表(像一串珍珠项链)
forward_list:单向链表(只能向前走的项链)
array:固定数组(固定大小的储物格)
关联容器 :元素按键值排序存储(像字典)
set:唯一键集合(不允许重复的集合)
multiset:可重复键集合(允许重复的集合)
map:键值对映射(像电话簿:名字→号码)
multimap:可重复键的映射(同名可以有多个号码)
无序关联容器 :哈希表实现(像乱放但能快速找到的抽屉)
unordered_set:无序唯一集合
unordered_map:无序键值映射
等等...
容器适配器 :特殊用途的包装
stack:栈(后进先出,像叠盘子)
queue:队列(先进先出,像排队)
priority_queue:优先队列(按优先级出队,像医院急诊)
1.2 容器的核心特性
关键点 1:模板
所有容器都是类模板 ,可以存储任何类型:
vector<int >
vector<string>
vector<vector<int >>
关键点 2:内存管理
值语义 :容器存储的是对象的副本
RAII 原则 :自动管理内存,离开作用域自动释放
异常安全 :保证基本异常安全
size():元素个数
empty():是否为空
begin()/end():迭代器
clear():清空
2. 算法(Algorithms)—— 操作的'说明书' 算法是操作数据的通用方法 ,就像一本说明书,告诉你如何对数据进行排序、查找、复制、删除等操作。
2.1 算法特点 关键特点 1:通用性
算法不关心具体容器类型,只通过迭代器操作数据:
sort (vector.begin (), vector.end ());
sort (deque.begin (), deque.end ());
关键特点 2:函数模板
算法都是函数模板 ,可以处理各种数据类型:
sort (int_vector.begin (), int_vector.end ());
sort (string_vector.begin (), string_vector.end ());
关键特点 3:迭代器依赖
算法通过迭代器访问容器元素,不直接操作容器本身。
2.2 算法分类
排序算法
sort:快速排序
stable_sort:稳定排序(相等元素保持原顺序)
partial_sort:部分排序
查找算法
find:线性查找
binary_search:二分查找(要求已排序)
lower_bound/upper_bound:边界查找
修改算法
copy:复制
fill:填充
replace:替换
remove:删除(实际是移动,需要配合 erase)
数值算法
accumulate:累加
inner_product:内积
adjacent_difference:相邻差
集合算法
set_union:并集
set_intersection:交集
set_difference:差集
sort ()
find ()
binary_search ()
3. 迭代器(Iterators)—— 访问的'指针' 迭代器是连接容器和算法的桥梁 ,它像是一个智能指针 ,知道如何在容器中移动并访问元素。
3.1 迭代器的作用 text
容器(数据存储) ←→ 迭代器(访问接口) ←→ 算法(操作逻辑)
遍历 :逐个访问容器元素
访问 :读写容器元素
连接 :让算法可以操作不同容器
3.2 迭代器分类(五种)
输入迭代器(Input Iterator)
只能读 ,不能写
只能向前 移动(单次)
像一次性读取器
例子:从键盘读取数据
输出迭代器(Output Iterator)
只能写 ,不能读
只能向前 移动
像打印机
例子:向屏幕输出
前向迭代器(Forward Iterator)
可以读写
只能向前 移动
可以多次遍历
例子:单向链表
双向迭代器(Bidirectional Iterator)
可以向前向后 移动
可以读写
例子:双向链表、红黑树
随机访问迭代器(Random Access Iterator)
可以任意跳跃访问
支持所有指针运算
例子:数组、vector、deque
3.3 迭代器失效问题 vector<int > v = {1 , 2 , 3 };
auto it = v.begin () + 1 ;
v.push_back (4 );
vector :插入/删除可能导致所有迭代器失效
deque :中间插入/删除会使所有迭代器失效
list/set/map :只影响被删除元素的迭代器
4. 仿函数(Functors)—— 行为的'函数对象' 仿函数是行为像函数的对象 ,它实际上是一个重载了 () 运算符的类对象 。
4.1 为什么需要仿函数?
可以保存状态
编译器可以内联优化
是对象 ,有类型信息
4.2 仿函数的使用
struct AddValue {
int value;
AddValue (int v) : value (v) {}
int operator () (int x) const {
return x + value;
}
};
AddValue add5 (5 ) ;
int result = add5 (10 );
4.3 STL 中的预定义仿函数
plus<T>:加法
minus<T>:减法
multiplies<T>:乘法
divides<T>:除法
modulus<T>:取模
negate<T>:取负
equal_to<T>:等于
not_equal_to<T>:不等于
greater<T>:大于
less<T>:小于
greater_equal<T>:大于等于
less_equal<T>:小于等于
logical_and<T>:与
logical_or<T>:或
logical_not<T>:非
sort (v.begin (), v.end (), greater <int >());
4.4 现代替代品:Lambda 表达式 C++11 引入 lambda 表达式,很多情况下替代仿函数:
struct Compare {
bool operator () (int a, int b) {
return a > b;
}
};
sort (v.begin (), v.end (), Compare ());
sort (v.begin (), v.end (), [](int a, int b) {
return a > b;
});
5. 适配器(Adapters)—— 接口的'转换器' 适配器是接口转换器 ,它修改现有组件的接口,使其适应新的需求。
5.1 三种适配器
基于现有容器提供新接口
三种主要类型:
stack:基于 deque/vector/list,提供栈接口
queue:基于 deque/list,提供队列接口
priority_queue:基于 vector,提供优先队列接口
template <typename T, typename Container = deque<T>>
class stack {
private :
Container c;
public :
void push (const T& value) {
c.push_back (value);
}
void pop () {
c.pop_back ();
}
T& top () {
return c.back ();
}
};
修改迭代器的行为
主要类型:
reverse_iterator:反向迭代器
insert_iterator:插入迭代器
stream_iterator:流迭代器
vector<int > v = {1 , 2 , 3 };
for (auto rit = v.rbegin (); rit != v.rend (); ++rit) {
cout << *rit << " " ;
}
修改函数对象的行为
在 C++11 后,很多被 bind/lambda 替代
主要类型:
binder1st/binder2nd:绑定参数(C++11 前)
not1/not2:逻辑取反
auto add = [](int a, int b) {
return a + b;
};
auto add5 = std::bind (add, std::placeholders::_1, 5 );
cout << add5 (10 );
三、五大组件如何协同工作
工作流程示例:排序一个 vector
vector<int > numbers = {5 , 2 , 8 , 1 , 9 };
auto begin = numbers.begin ();
auto end = numbers.end ();
sort (begin, end);
sort (begin, end, greater <int >());
copy (numbers.rbegin (), numbers.rend (), ostream_iterator <int >(cout, " " ));
text
数据 → 存入容器 → 迭代器访问 → 算法处理 → 结果输出
组件间的松耦合设计
容器和算法分离 :算法通过迭代器操作容器,不依赖具体容器类型
迭代器作为粘合剂 :统一了不同容器的访问方式
仿函数提供策略 :允许自定义操作行为
适配器扩展功能 :不改动原有代码,增加新功能
四、总结:五大组件的关系比喻
容器 = 书架、储物柜(各种存储设施)
vector:一排可以扩展的书架
list:用链条连接的书格
map:按书名排序的目录柜
set:不允许重复的珍本书架
算法 = 图书管理方法
sort:按某种规则整理书籍
find:查找特定书籍
copy:复印书籍
remove:下架旧书
迭代器 = 图书管理员的手/扫码枪
可以指向特定位置
可以移动到相邻位置
可以读取书籍信息
连接书架(容器)和管理方法(算法)
仿函数 = 智能工具/规则
按作者排序的规则
按出版日期筛选的条件
自动贴标签的机器
适配器 = 转换接口
把普通书架变成只能从顶部取书的'栈式书架'
把书架变成只能从一端取书的'队列式书架'
反向阅读器(从后向前读)
整个系统工作流程:
管理员(算法)使用扫码枪(迭代器)按照特定规则(仿函数)在书架(容器)上操作,通过特殊设备(适配器)满足特殊需求。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online