不能直接用erase单干删除vector中指定值,否则会因下标偏移导致跳删或越界;应使用erase-remove惯用法:先remove_if重排保留元素,再erase截断冗余部分。

直接删 vector 里某个值会崩?别用 erase 单干
想删掉 vector 中等于某个值的元素,比如所有 5,直接循环调 erase 是最常见也最危险的做法。它会改变后续元素的下标,导致跳过下一个元素,甚至越界访问。
典型错误写法:
for (size_t i = 0; i < v.size(); ++i) {
if (v[i] == 5) v.erase(v.begin() + i); // ❌ i 没减,下个元素被跳过
}
- 用
erase后必须手动调整索引(--i),但容易漏、难维护 - 每次
erase都触发内存搬移,O(n) 复杂度,频繁删除时性能极差 - 迭代器失效:
erase返回新有效迭代器,原迭代器立刻失效,继续用就 UB
remove 不是真删,它是“搬走+返回新尾”
std::remove 名字极具误导性——它不删任何东西,也不改变容器大小。它只是把所有不匹配的元素往前挪,返回一个指向“逻辑新结尾”的迭代器。
真正删,得配 erase 一起用,这就是经典的 erase-remove 惯用法:
立即学习“C++免费学习笔记(深入)”;
v.erase(std::remove(v.begin(), v.end(), 5), v.end());
-
std::remove是算法,对任意迭代器范围生效,不依赖vector - 它只做一次遍历,移动操作是 memmove 级别,比反复
erase快得多 - 注意:它不保证被“移走”的元素值不变(可能被覆盖),别依赖它们
要删满足条件的元素?换 remove_if
删值是特例,更多时候你要删满足某条件的元素,比如“大于 10 的偶数”或“指针为空”。这时必须用 remove_if:
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x > 10 && x % 2 == 0; }), v.end());
- lambda 或函数对象必须返回
bool,true表示“该删”,但它实际是“该留下”的反义——remove_if留下false的元素 - 和
remove一样,它不改变容器 size,必须配合erase才真删 - 不能用在
list上追求性能:list::remove_if是成员函数,原地删,更高效
为什么不能只用 remove 就完事?
因为 std::remove 只重排数据,vector 的 size() 和 capacity() 完全不变。残留的“脏数据”还在内存里,下次遍历时若没截断,就会读到旧值。
- 假设
v = {1,5,3,5,7},remove(..., 5)后内容变成{1,3,7,5,7},但v.size()还是 5 - 如果不接
erase,后续for (auto x : v)会遍历出1,3,7,5,7—— 第四个 5 是上次留下的垃圾 - 调试时看到奇怪值,八成是忘了 erase,不是 remove 写错了
erase-remove 是两步不可拆,少一步,结果就不对。很多人卡在这儿,不是不会写,是没意识到 remove 根本不改容器结构。










