用erase+find删除单个匹配元素需先find定位再erase,且必须检查it!=end()避免越界;erase+remove(erase-remove惯用法)可高效删除所有匹配元素,remove前移元素并返回新逻辑尾迭代器,再由erase真正删除;不可边遍历边erase,否则迭代器失效导致未定义行为。

用 erase + find 删除单个匹配元素
直接调用 erase 不能传值,必须传迭代器。所以得先用 find 定位,再擦除。常见错误是忽略 find 返回 end() 的情况,导致越界擦除:
std::vector<int> v = {1, 2, 3, 2, 4};
auto it = std::find(v.begin(), v.end(), 2);
if (it != v.end()) {
v.erase(it); // 只删第一个 2
}</int>
注意:擦除后原迭代器失效,it 不可再用;且该操作时间复杂度为 O(n),因为 find 遍历 + erase 移动后续元素。
用 erase + remove 删除所有匹配元素(推荐)
std::remove 不是真的删除,而是把不匹配的元素前移,返回新逻辑尾部的迭代器,再配合 erase 一次性擦除“被覆盖”部分——这就是常说的 erase–remove 惯用法:
std::vector<int> v = {1, 2, 3, 2, 4, 2};
v.erase(std::remove(v.begin(), v.end(), 2), v.end()); // 所有 2 都没了</int>
容易踩的坑:
-
remove是算法,不改变容器大小,必须配erase才真正释放内存 - 对自定义类型,要确保
operator==正确重载 - 如果用
remove_if,谓词里别修改容器,否则迭代器可能失效
删除满足条件的多个元素(比如大于 5 的数)
这时必须用 remove_if:
std::vector<int> v = {1, 6, 3, 8, 4};
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x > 5; }), v.end());</int>
关键点:
- lambda 捕获列表里不要按引用捕获正在被遍历的
v - 不能在 lambda 里调用
v.erase()或其他会改变 size/迭代器的函数 - 性能上仍是
O(n),但比手写循环 + 多次erase快得多(后者最坏O(n²))
为什么不能边遍历边 erase?
这是新手高频崩溃点。下面代码会出错:
for (auto it = v.begin(); it != v.end(); ++it) {
if (*it == 2) v.erase(it); // ❌ it 失效,++it 行为未定义
}
正确做法只有两种:
- 用 erase–remove 惯用法(最安全、最常用)
- 若必须手动遍历,得用
while并保存erase返回的下一个有效迭代器:it = v.erase(it),此时不执行++it
真正麻烦的不是语法,而是误以为 erase 返回 void ——它其实返回下一个有效的迭代器,这个细节常被忽略。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











