删除vector中第一个值为x的元素应先用std::find查找,再检查是否找到(it != v.end())后erase;删所有匹配项须用erase-remove惯用法;按索引删需用v.erase(v.begin()+i)并确保索引有效。

用 erase 配合 find 删除单个匹配元素
想删掉 vector 里第一个值为 x 的元素?别手写循环找下标再删——下标可能越界,删完迭代器还失效。直接用标准组合:std::find 找位置,erase 删它。
常见错误是写了 v.erase(std::find(v.begin(), v.end(), x)) 却没检查是否找到:如果 x 不在容器里,find 返回 v.end(),传给 erase 就是未定义行为(多半 crash)。
- 必须先判断:
auto it = std::find(v.begin(), v.end(), x); if (it != v.end()) v.erase(it); -
find要求元素支持==比较;自定义类型得重载operator== - 只删第一个匹配项;要删所有,得用下面的方法
删掉所有满足条件的元素,用 remove_if + erase 惯用法
这是 C++ 里最常被写错的点:有人直接循环调 erase,结果删着删着迭代器飞了,或者漏删相邻元素。正确姿势是「逻辑删除 + 物理收缩」两步走:remove_if 把要留的元素往前挪,返回新逻辑尾部,再用 erase 一次性干掉后面那段。
比如删掉所有偶数:
立即学习“C++免费学习笔记(深入)”;
std::vector<int> v = {1,2,3,4,5,6};
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; }), v.end());
-
remove_if不真正删除,只重排,时间复杂度 O(n),比反复erase快得多 - lambda 捕获要注意:若需访问外部变量,记得加
[&]或显式列出 - 这个惯用法叫 Erase–remove idiom,不是 bug 是设计模式
按索引删除时,注意 erase 的参数类型和边界
如果已知下标 i,想删第 i 个元素,别写 v.erase(i) ——erase 不接受整数索引,只接受迭代器。正确写法是 v.erase(v.begin() + i)。
容易踩的坑:
- 下标
i必须满足0 <= i && i < v.size(),否则v.begin() + i是非法迭代器 - 删完后,原下标 >
i的元素会前移,后续操作别还按旧索引算 - 用
at(i)替代[i]可触发越界检查(抛std::out_of_range),但不解决逻辑问题
删空 vector 后,内存不一定立刻释放
v.clear() 或反复 erase 到空,只是把 size 变 0,capacity 通常不变。下次 push_back 还能复用老内存,这不算 bug,是性能优化。
但如果你明确要归还内存(比如处理完一批大数据后),得手动缩容:
-
v.shrink_to_fit();—— C++11 起支持,但只是“建议”,实现可忽略 - 更可靠写法:
std::vector<T>(v).swap(v);,靠临时对象重建 + 交换强制释放 - 频繁增删场景,考虑换
std::deque,它头尾删更快,且 capacity 更灵活
真正麻烦的是在多线程里删 vector 元素——所有操作都非原子,没加锁就并发读写,崩得毫无征兆。











