C++ 容器中の erase
一、erase 方法的功能定位
vector 的 erase 方法是 STL 中用于从容器中移除元素的核心函数,其主要功能是:
从 vector 中删除单个元素或一段连续范围内的元素
调整容器大小以反映元素数量的变化
维护剩余元素的连续性和内存布局
返回一个迭代器,指向被删除元素的下一个元素
erase 方法是破坏性操作,会改变容器的状态和内部布局,同时可能影响现有迭代器的有效性。
二、迭代器参数的语法特征与使用场景
vector 的 erase 方法有两种重载形式,分别适用于不同的删除场景:
2.1 单个元素删除
1 | iterator erase(iterator position); |
参数:指向要删除元素的迭代器
返回值:指向被删除元素下一个元素的有效迭代器
使用场景:已知要删除元素的确切位置时
2.2 范围元素删除
1 | iterator erase(iterator first, iterator last); |
参数:
first:指向要删除范围中第一个元素的迭代器
last:指向要删除范围中最后一个元素之后位置的迭代器
返回值:指向最后一个被删除元素下一个元素的有效迭代器
使用场景:需要删除一段连续元素时,如删除满足特定条件的元素序列
三、内存重组机制与性能影响
3.1 底层实现原理
当调用 erase 方法时,vector 会执行以下操作:
- 确定需要删除的元素范围
- 将删除位置之后的所有元素向前移动,覆盖被删除的元素
- 调整容器的 size(元素数量),但不改变 capacity(容量)
- 析构最后一个元素(已被移动的元素副本)
3.2 性能分析
单个元素删除:时间复杂度为 O (n),因为删除位置后的所有元素都需要向前移动一个位置
范围删除:时间复杂度为 O (n),其中 n 是容器中剩余元素的数量
空间复杂度:O (1),不需要额外的存储空间
性能影响因素:
删除位置:删除靠前的元素比删除靠后的元素需要移动更多元素
容器大小:大型容器上的 erase 操作成本更高
元素类型:移动复杂类型元素比移动基本类型元素成本更高
四、典型代码示例及执行结果
4.1 单个元素删除示例
1 | #include <vector> |
4.2 范围元素删除示例
1 | #include <vector> |
4.3 循环中删除元素的正确方式
1 | #include <vector> |
五、迭代器失效问题及解决方案
5.1 迭代器失效的原因
erase 操作会导致以下迭代器失效:
所有指向被删除元素的迭代器
所有指向被删除元素之后位置的迭代器
容器的 end () 迭代器
原因是 erase 操作会移动元素,改变了这些迭代器所指向的内存位置的语义。
5.2 解决方案
使用 erase 的返回值:erase 返回的迭代器是唯一保证有效的迭代器,指向被删除元素的下一个元素
1 | auto it = vec.begin(); |
重新获取迭代器:在批量删除后,如果需要继续使用迭代器,应重新获取
使用索引而非迭代器:在某些场景下,使用索引操作可以避免迭代器失效问题
六、常见错误及规避策略
6.1 常见错误
删除后继续使用失效的迭代器
1 | auto it = vec.begin(); |
循环中错误地递增迭代器
1 | for (auto it = vec.begin(); it != vec.end(); ++it) { |
使用无效范围
1 | vec.erase(vec.begin() + 5, vec.begin() + 3); // 错误:范围无效,first > last |
对空容器使用 erase
1 | vector<int> vec; |
6.2 规避策略
- 始终使用 erase 的返回值更新迭代器
- 在删除操作前检查容器是否为空
- 确保范围删除时 [first, last) 是有效的半开区间
- 避免在循环中同时使用多个迭代器进行删除操作
- 对于复杂删除逻辑,考虑先标记再删除的方式