不能用正向for循环边遍历边erase,因为每次erase会使后续元素前移、下标改变,导致跳删或越界;反向遍历可避免索引偏移,但性能差且易错;推荐使用erase-remove惯用法——先remove_if重排保留元素,再erase截断冗余部分,一次遍历、安全高效。

为什么不能用正向 for 循环边遍历边 erase
直接写 for (int i = 0; i 然后在循环体内调用 <code>vec.erase(vec.begin() + i),会导致越界或漏删。因为 erase 后,后续元素前移,i 却照常自增,相当于跳过了下一个位置的元素。
反向遍历删除的正确写法(vector)
从最后一个索引开始递减,删除时不干扰前面未处理的元素索引。关键点是:用有符号整型(如 int 或 ssize_t),避免无符号下溢成极大值。
for (int i = static_cast<int>(vec.size()) - 1; i >= 0; --i)</int>- 判断条件成立时调用
vec.erase(vec.begin() + i) - 注意:每次
erase都会触发内存移动,频繁删除性能差
示例:
std::vector<int> vec = {1, 2, 3, 4, 5, 3, 6};
for (int i = static_cast<int>(vec.size()) - 1; i >= 0; --i) {
if (vec[i] == 3) {
vec.erase(vec.begin() + i);
}
}
// 结果:{1, 2, 4, 5, 6}
</int></int>
更推荐的方案:erase–remove 惯用法
它不依赖遍历方向,一次移动完成所有删除,效率高且安全。本质是把不满足条件的元素“前移”,再统一擦除尾部冗余段。
- 对
vector:用std::remove_if+erase - 注意
std::remove_if不真正删除,只重排;必须接erase才生效 - lambda 捕获需谨慎,避免悬垂引用
示例:
std::vector<int> vec = {1, 2, 3, 4, 5, 3, 6};
vec.erase(
std::remove_if(vec.begin(), vec.end(), [](int x) { return x == 3; }),
vec.end()
);
</int>
原生数组不能直接 erase,得自己管理长度
C++ 原生数组(如 int arr[10])大小固定,无法动态增删。所谓“删除”只能是逻辑上的:维护一个有效长度 len,把要删的元素挪到末尾,再递减 len。
- 反向遍历时,若要删
arr[i],可 swap 到末尾:std::swap(arr[i], arr[--len]); - 必须自己跟踪
len,访问时只用arr[0]到arr[len-1] - 没有自动内存释放,也不支持 STL 算法,容易出错
所以,除非嵌入式等硬性限制,否则优先用 std::vector。
反向遍历只是绕开索引偏移问题的权宜之计;真正健壮、高效的做法,是用 erase–remove。而原生数组的“删除”本质上是手动维护有效区间,稍不留神就踩越界或逻辑错位的坑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











