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 <forward_list>
#include <iostream>
int main() {
// 空构造
std::forward_list<int> fl1;
// 初始化列表构造(C++11 起)
std::forward_list<int> fl2 = {1, 2, 3, 4, 5};
// 拷贝构造
std::forward_list<int> fl3 = fl2;
// 从迭代器范围构造(注意:forward_list::before_begin() 不是标准用法,需用 insert_after)
std::forward_list<char> 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<int> 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 <iterator>
std::forward_list<std::string> 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<int> a = {1, 2};
std::forward_list<int> b = {3, 4, 5};
// 将 b 全部移到 a 开头之后(即插入到 a.begin() 之后)
a.splice_after(a.before_begin(), b); // a → 1,3,4,5,2;b 变为空










