vector和string的erase返回下一个有效迭代器,用于安全遍历;list/forward_list删后需手动赋值新迭代器;关联容器erase后仅被删迭代器失效,须用next保存或key删除;推荐remove-erase惯用法。

vector 和 string 的 erase 返回值不是 void
很多人以为 erase 只是删掉元素就完事,结果在循环里边删边 ++ 迭代器,直接触发未定义行为。根本原因是:vector 和 string 的 erase 会**使被删位置及之后所有迭代器失效**,但它的返回值恰恰是**下一个有效迭代器**——这个设计就是为了让你安全续遍历。
- 错误写法:
for (auto it = v.begin(); it != v.end(); ++it) { if (*it == x) v.erase(it); }→it被删后失效,++it 是野指针操作 - 正确写法:
for (auto it = v.begin(); it != v.end(); ) { if (*it == x) it = v.erase(it); else ++it; } -
v.erase(it)删除it指向元素,并返回新有效的迭代器(指向原it+1位置);没删就手动++it - 注意:
erase的单迭代器重载在 C++11 后才返回迭代器,C++98 不支持,别在老项目里硬套
list 和 forward_list 的 erase 不会让其他迭代器失效
链表类容器的节点内存不连续,删一个节点只影响它自己的迭代器,前后都不动。所以你可以用更直觉的方式删,但仍有陷阱。
-
list::erase(it)返回void,不能靠返回值续遍历 - 安全写法仍是:
if (cond) it = lst.erase(it); else ++it;—— 因为erase后it已无效,必须重新赋值 - 别写
lst.erase(it++);:虽然it++返回临时副本,但 C++ 标准不保证erase和++的求值顺序,有编译器差异风险 -
forward_list没有++it的随机访问能力,必须用next(it)或改用before_begin()配合erase_after
map / set / unordered_map / unordered_set 的 erase 返回 void
关联容器删元素时,只有被删的那个迭代器失效,其余全保留。但它们的 erase 不返回新迭代器,所以不能像 vector 那样依赖返回值续遍历。
- 常见错误:
for (auto it = m.begin(); it != m.end(); ++it) { if (bad(*it)) m.erase(it); }→it失效后 ++ 是 UB - 安全做法只有两种:
– 先保存next:for (auto it = m.begin(); it != m.end(); ) { auto next = std::next(it); if (bad(*it)) m.erase(it); it = next; }
– 或用 key 删:if (bad(*it)) m.erase(it->first);(仅限 map/set;unordered 系列也支持) -
unordered_map::erase(key)是 O(1) 平摊,比迭代器删更稳,且不涉及迭代器生命周期问题 - 注意:
erase(it)后it立即不可用,哪怕你马上给它赋新值,也不能在 erase 前对它做任何读/++ 操作
用 remove-erase 惯用法替代手写循环
对 vector/string 这类支持随机访问的容器,与其自己管理迭代器,不如交给算法组合处理——既简洁又避免手误。
立即学习“C++免费学习笔记(深入)”;
-
std::remove不真删,只是把要留的元素往前挪,返回新逻辑尾部;erase再按范围清掉多余部分 - 写法:
v.erase(std::remove(v.begin(), v.end(), x), v.end());或用 lambda:v.erase(std::remove_if(v.begin(), v.end(), [](int a){return a - 优势:无迭代器失效风险、代码短、可读性高;劣势:会移动所有保留元素,对大对象可能比逐个 erase 更慢
- 不适用于 list/map 等不支持随机迭代器的容器——
std::remove要求前向迭代器以上,而 list 是双向,map 是双向但 value_type 是 const,编译不过
迭代器失效的本质是容器内部结构变动导致原有指针/引用/迭代器指向了非法内存或逻辑位置。最常被忽略的一点是:不同容器的 erase 接口语义根本不统一,靠“记住一种写法走天下”一定会翻车。









