一般来讲erase用得比较多,不注意也容易踩坑,例如:
vector<int> vec{1, 4, 3, 2, 5, 2};
for(auto it = vec.begin(); it != vec.end(); it++){
if(*it < 3){
cout << "num is " << *it << endl;
it = vec.erase(it);
if(it == vec.end()) break;
}
}
这个代码如果不在for循环里加上最后的判断会导致错误,原因在于,当it指向最后一个2时,满足删除条件,删除后it变成了end,然后又做了++操作,导致越界。
类似的坑还有许多,这里就不一一列举了,总之,它们的共同点在于对vector进行删除时都不够优雅,需要进行一些额外的处理避免误操作。
我们完全可以使用<algorithm>提供的remove和remove_if方法,配合erase进行删除。这两个方法并不是真的删除元素,而是以覆盖的方式将满足删除条件的元素移到容器最后(它们具体的实现方式很有意思,但是这里从略,总之有两点:1)它们并没有真的删除元素;2)它们使用了“覆盖”的方式,将要删除的元素移到最后,因此这些元素可能因为被覆盖过而发生改变,但这已经不重要了),然后返回指向第一个要删除位置的迭代器。这样一来,删除就优雅多了,例如:
vec.erase(remove(vec.begin(), vec.end(), 3), vec.end());
如果再用上lambda,看起来会更酷:
vec.erase(remove_if(vec.begin(), vec.end(), [](int x){return x == 3;}), vec.end());
可以抽成自己的工具类:
void remove_v2(vector<int>& v,int val) {
v.erase(remove(v.begin(), v.end(), val), v.end());
}
reference:
[1]. https://blog.csdn.net/lishichengyan/article/details/82669153