1. C++向量中 erase 的基本语义
1.1 erase 的返回值与迭代器行为
在 C++ 的向量中,erase 用于删除一个元素或一个元素区间。它的语义是将区间内的元素移除,并返回指向后继元素的新迭代器。返回值始终指向被删除区间后面的那个元素,若删除的是最后一个元素,则返回 end()。
迭代器失效方面,vector 的 erase 会导致位于删除点及其之后的所有迭代器和引用失效;这意味着在进行删除后,原有的遍历迭代器很可能无效。理解这一点对正确写循环删除非常关键。
1.2 erase 的基本用法示例
删除单个元素时,通常要获取该元素的迭代器并调用 erase。调用后返回的新迭代器应被重新赋值,以便继续遍历。
关键点:不要在尚未获取新迭代器之前继续使用旧的迭代器;否则很可能触发未定义行为。
std::vector a{1,2,3,4,5};
auto it = std::find(a.begin(), a.end(), 3);
if (it != a.end()) {it = a.erase(it); // 返回后继元素的迭代器
}
for (; it != a.end(); ++it) {// 继续处理
}
2. 使用 erase 的正确姿势
2.1 在遍历时安全删除元素的模式
在遍历向量时删除元素,直接使用 for(auto x : vec) 的范围遍历会导致难以控制的迭代问题,因此应使用标准迭代器并在删除后获得新的迭代器。
常用模式:用一个循环维护一个可更新的迭代器,遇到需要删除的元素时调用 erase 并将返回值赋给迭代器,否则继续自增。
std::vector v{1,2,3,4,5,6};
for (auto it = v.begin(); it != v.end(); ) {if (*it % 2 == 0) {it = v.erase(it);} else {++it;}
}
要点:erase 会改变容器大小并使后续元素前移,迭代器需要重新获取;

2.2 erase 的区间删除
删除一个连续区间时,使用 erase 的区间版本,传入两个迭代器,返回值指向区间后面的元素的迭代器。
std::vector v{1,2,3,4,5,6};
auto new_end = v.erase(v.begin()+1, v.begin()+4); // 删除 2,3,4
返回值:新返回的迭代器指向被删除区间后的元素,若删除的是尾部,则返回 end()。
3. 常见误区与安全实践
3.1 误区:在范围 for 循环中直接调用 erase
将 erase 放在范围 for 循环中很容易导致迭代器失效或越界错误。使用传统的迭代器循环或 erase-remove idiom 可以避免这个问题。
解决方法:避免在 range-for 中直接删除,改用手动迭代器或 std::remove_if 加上 erase 的组合。
// 错误示例:不应在范围 for 中删除元素
// for (auto x : v) { if (条件) v.erase(...); }// 正确示例:手动迭代器
for (auto it = v.begin(); it != v.end(); ) {if (满足条件) it = v.erase(it); else ++it;
}
容量与迭代器关系:删除并不会缩减 capacity,但会减少 size,元素移动会影响后续迭代器。
3.2 使用 erase-remove idiom 的意义
在需要按谓词删除元素时,erase-remove idiom 是最简洁高效的做法。它将删除逻辑与实际清理分离,避免多次移动。
std::vector v{1,2,3,4,5,6};
auto it = std::remove_if(v.begin(), v.end(), [](int x){ return x % 2 == 0; });
v.erase(it, v.end());
4. 高级用法与性能要点
4.1 结合 remove_if 的非破坏性删除策略
在某些场景下,先用 remove_if 标记需要保留的元素,再一次性清理无用位置,可以减少多次移动的开销。
性能要点:erase 操作的复杂度与删除的元素数量成线性关系,尽量减少删除区间的长度以降低搬移成本。
// 结合 remove_if 与 erase 的典型做法
std::vector v{ /* ... */ };
v.erase(std::remove_if(v.begin(), v.end(), [](int x){ return x < 0; }), v.end());
4.2 其他注意事项
当向量具有保留容量时,erase 不会对 capacity 的回收造成直接影响;如果需要回收容量,可能需要使用 shrink_to_fit 或把数据搬到新的向量。
进一步的实战要点:如果删除比例较高,考虑先估算成本、再选择直接区间删除还是逐个删法,避免不必要的搬移开销。


