std::forward_list是c++11引入的单向链表,内存小、插入删除O(1),但不支持随机访问、反向遍历和size(),操作依赖insert_after/erase_after及before_begin()。

std::forward_list 是 C++11 引入的单向链表容器,内存占用小、插入删除快(仅需常数时间),但不支持随机访问、不能反向遍历,且没有 size() 成员函数(需用 std::distance 或手动计数)。
初始化与基本操作
forward_list 没有容量概念,构造时只支持空构造、初始化列表、拷贝/移动构造,以及从另一个 forward_list 构造(带迭代器范围)。
示例:
#include #include int main() { // 空构造 std::forward_list fl1; // 初始化列表构造(C++11 起) std::forward_list fl2 = {1, 2, 3, 4, 5}; // 拷贝构造 std::forward_list fl3 = fl2; // 从迭代器范围构造(注意:forward_list::before_begin() 不是标准用法,需用 insert_after) std::forward_list fl4; fl4.push_front('c'); fl4.push_front('b'); fl4.push_front('a'); // 此时为 a → b → c return 0; }
插入与删除操作
forward_list 的插入和删除必须通过“前驱节点”进行,因此所有修改操作都围绕 insert_after 和 erase_after 展开。它提供 before_begin() 迭代器(指向逻辑头节点之前),用于在开头插入。
立即学习“C++免费学习笔记(深入)”;
常用方法:
- push_front(val):在开头插入元素(等价于 insert_after(before_begin(), val))
- pop_front():删除第一个元素(若非空)
- insert_after(pos, val):在 pos 所指节点之后插入 val(pos 必须有效,可为 before_begin())
- erase_after(pos):删除 pos 后的一个节点(pos 可为 before_begin(),即删首节点)
- remove(val):移除所有等于 val 的元素
- remove_if(pred):移除满足谓词 pred 的元素
示例:
std::forward_list fl = {10, 20, 30, 40}; fl.push_front(5); // → 5,10,20,30,40 fl.pop_front(); // → 10,20,30,40 auto it = fl.before_begin(); std::advance(it, 1); // 移动到第2个元素前(即指向10节点前)→ 实际指向10 fl.insert_after(it, 15); // 在10后插入15 → 10,15,20,30,40 fl.erase_after(fl.before_begin()); // 删除首节点(10)→ 15,20,30,40 fl.remove(30); // → 15,20,40 fl.remove_if([](int x) { return x > 25; }); // → 15,20
遍历与查找
forward_list 只支持单向迭代,begin() 返回首个元素迭代器,end() 返回尾后迭代器。遍历时不能使用索引,只能靠 ++it 前进。
获取长度需用 std::distance:
#include std::forward_list names = {"Alice", "Bob", "Charlie"}; size_t len = std::distance(names.begin(), names.end()); // len == 3 // 遍历打印 for (auto it = names.begin(); it != names.end(); ++it) { std::cout << *it << " "; } // 输出:Alice Bob Charlie
实用技巧与注意事项
forward_list 的设计强调最小开销:每个节点只存一个指针(next),无 size 字段、无尾指针、无 reverse_iterator。因此某些操作比 list/vector 更轻量,但也更受限。
关键提醒:
- 迭代器失效规则宽松:只有被删除节点的迭代器失效;插入不影响其他迭代器
- splice_after 可高效拼接两个 forward_list(O(1)),类似 list::splice,但参数是 after-where 和 source range
- 若需频繁查长度,建议自行维护变量,避免反复调用 std::distance(O(n))
- 不支持 data()、at()、[]、rbegin() 等双向/随机访问接口
拼接示例:
std::forward_list a = {1, 2}; std::forward_list b = {3, 4, 5}; // 将 b 全部移到 a 开头之后(即插入到 a.begin() 之后) a.splice_after(a.before_begin(), b); // a → 1,3,4,5,2;b 变为空