forward_list 不支持 --it,因其为单向链表、迭代器仅是前向类型;所有增删操作均基于 insert_after/erase_after;erase_after 返回新有效迭代器以安全遍历删除;size() 通常为 o(n),非 o(1)。

forward_list 为什么不能像 list 那样用 iter--
forward_list 是 C++11 引入的单向链表容器,底层只存 next 指针,没有前驱引用。这意味着它的迭代器是 forward_iterator 类型,**不支持递减(--it)或反向遍历**。试图写 it-- 或 it -= 2 会编译失败,错误信息类似:no match for operator--。
如果你需要从后往前操作,得靠额外变量缓存上一个位置,或者改用 list(双向)——但代价是内存多一倍指针开销。
insert_after 和 erase_after 是核心操作入口
forward_list 所有插入、删除都围绕「在某个已知节点之后」展开,因为没法高效定位前驱。它没有 insert(pos, val) 这种基于任意位置的重载,只有 insert_after;同理,只有 erase_after,没有 erase(pos)。
常见用法:
- 用
before_begin()获取逻辑上的“头前哨”,配合insert_after实现头插:fl.insert_after(fl.before_begin(), 42); - 删除第一个元素:用
erase_after(fl.before_begin()) - 遍历时删当前元素?不行——必须先保存
prev迭代器,再对它调erase_after
遍历 + 删除元素时怎么避免迭代器失效
forward_list::erase_after 返回被删节点的下一个有效迭代器(C++11 起),这是关键设计。它让你能安全地边遍历边删,而不用手动 ++ 后再检查是否到尾。
典型模式:
auto prev = fl.before_begin();
while (prev != fl.end() && std::next(prev) != fl.end()) {
auto curr = std::next(prev);
if (should_remove(*curr)) {
prev = fl.erase_after(prev); // 返回新 prev,指向被删节点的后继
} else {
prev = curr;
}
}
漏掉这一步直接 ++prev,可能让 prev 指向已释放内存,尤其在 erase_after 后 —— 这是新手最常踩的坑。
size() 不是 O(1),别默认它和 vector 一样快
forward_list::size() 在标准库实现中通常是 O(n),因为它不维护长度计数器(省空间)。如果你频繁调用 size() 做判断(比如 while (fl.size() > 0)),性能会明显变差。
替代方案:
- 用
!fl.empty()判断非空,O(1) - 真要长度,自己维护一个
size_t count变量,每次push_front/erase_after时手动更新 - 确认你用的 STL 版本是否优化了
size()(如 MSVC 某些版本加了计数,但不可移植)
单向链表的取舍很实在:换来了小内存占用和头插/头删 O(1),代价是失去随机访问、反向迭代、常数 size 查询——用之前得想清楚哪条路更痛。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











