1. 核心概念:erase 与 remove 的职责分工
1.1 erase 的定位与返回值
vector 的 erase 成员函数用于直接从容器中移除一个或一个区间元素,它会修改底层存储并返回一个指向删除后第一个元素的迭代器(若删除的是一个区间,返回的是区间后第一个元素的迭代器)。
注意点:erase 会使删除位置之后的元素前移,因此涉及移动、赋值和析构等操作;返回值可以继续作为迭代器进行后续遍历,避免迭代器失效带来的麻烦。
1.2 remove 的定位与返回值
std::remove 属于算法库,不是 vector 的成员,它不会缩容容器的大小,而是把需要保留的元素向前移动,返回一个新的逻辑结束位置(新的 end 迭代器)。
在常见的“删除所有符合条件的元素”的实现中,remove 通常与 erase 连用;因为 remove 仅仅移动元素并标记末尾区域为“已删除”,需要通过 erase 将容器实际缩容。
2. erase 的基本用法与注意点
2.1 删除单个元素
用法要点:v.erase(it) 会删除迭代器 it 指向的元素,并返回一个指向删除后位置的迭代器。
需要注意:erase 会使被删除元素的迭代器失效,因此应立即使用返回的新迭代器继续遍历;对无效迭代器执行解引用或自增是未定义行为。
2.2 删除一个区间
用法要点:v.erase(v.begin() + l, v.begin() + r) 删除下标从 l 到 r-1 的区间,返回值是指向删除后第一个元素的迭代器。如果区间为空,返回原迭代器。
复杂度与影响:区间 erase 的时间复杂度与区间长度相关,通常为 O(n);大量元素移动会影响性能,需要结合场景选择策略。
2.3 代码示例:简单擦除单元素
#include <vector>
#include <iostream>
using namespace std;int main() {vector<int> v{1,2,3,4,5};auto it = v.erase(v.begin() + 2); // 删除元素 3,返回指向 4 的迭代器for(int x: v) cout << x << ' ';cout << '\\n';return 0;
}
3. remove 的工作原理与常见陷阱
3.1 remove 的本质
std::remove 会把需要移除的元素向前移动,保留剩余元素的顺序,并返回一个新的结束迭代器。需要理解的是它并不会改变容器大小。
如果不再进一步缩容,容器的容量与大小将保持不变,后面的“被移动”的元素在容器末端仍然存在某种意义上的占用,直到调用 erase。
3.2 remove_if 与谓词模板
std::remove_if 可以接收谓词,对所有使谓词为 true 的元素进行移除逻辑处理,返回新的结束迭代器。
结合 remove_if,可以对复杂条件进行删除,而不需要改动遍历逻辑,提升代码可读性。
4. 典型场景:erase–remove idiom 的完整示例
4.1 移除所有等于某值的元素
核心模式:v.erase(std::remove(v.begin(), v.end(), value), v.end());
先用 remove 将要删除的元素移动到末端,返回新的结束迭代器,再通过 erase 缩容向量,达到实际删除的效果。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;int main() {vector<int> v{1,2,3,2,4,2,5};int value = 2;auto new_end = std::remove(v.begin(), v.end(), value);v.erase(new_end, v.end());for (int x : v) cout << x << ' ';cout << '\\n';
}
4.2 使用谓词删除
示例:删除偶数:通过 remove_if 与 erase 的组合实现。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;bool is_even(int x) { return x % 2 == 0; }int main() {vector<int> v{1,2,3,4,5,6};auto new_end = std::remove_if(v.begin(), v.end(), is_even);v.erase(new_end, v.end());for (int x : v) cout << x << ' ';cout << '\\n';
}
5. erase 与 remove 的对比要点与陷阱
5.1 迭代器失效问题与遍历方式
erase 会使相关迭代器失效,在循环中删除时应采用返回的新迭代器来继续遍历,避免越界或错误处理。
5.2 性能与内存考虑
若一次性删除大量元素,直接逐个 erase 或区间 erase 的成本可能较高;采用 erase–remove idiom 可以把多次移动合并成一次线性移动,提升性能。
5.3 与容器类型的差异
与 list 等容器不同,vector 的 erase 要求连续内存,因此在频繁删除时需要考虑缓存局部性和内存再分配的影响。
6. 进阶技巧:结合迭代器安全删除和范围删除
6.1 使用区间删除替代多个单元素删除
区间删除在删除一段连续区间时更高效,减少了迭代器更新的数量和移动的次数。
#include <vector>
#include <iostream>
using namespace std;int main() {vector<int> v{1,2,3,4,5,6,7,8};// 删除中间的 3 到 6v.erase(v.begin() + 2, v.begin() + 6);for (int x : v) cout << x << ' ';cout << '\\n';
}



