STL利用迭代器iter遍历删除的bug(插入类似)
部分参考:
c++ vector list map在遍历中删除元素_m4vsak123的专栏-CSDN博客
stl vector/list如何一边遍历一边删除_Coder-CSDN博客
为什么会遍历删除失败?
// 遍历1
auto tb = lll.begin(), te= lll.end();
for(;tb!=te;){
lll.erase(tb);
++tb;
// 遍历2
for(;tb!=lll.end();){
lll.erase(tb);
++tb;
}
两种遍历方法有什么区别?遍历2每次都会请求end的位置,而遍历1只请求一次然后缓存,如果使用vector遍历的同时删除,那么就会导致后续的vector迭代器失效( vector删除元素会把后面的元素整体迁移填补前面的缺失),比如之前缓存的end(),但是List底层是链表,反而幸免于难。
- 一个具体一点的例子:
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int>d{1,2,3,4};
for(vector<int>::iterator it=d.begin();it!=d.end();it++)
d.erase(it);
for(auto i:d){
cout<<i<<endl; // 2,4
}
有意思的是:如果是奇数会导致Segmentation fault,因为iter删除填补后会跳过end导致越界。
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int>d{1,2,3};
for(vector<int>::iterator it=d.begin();it!=d.end();it++)
d.erase(it);
for(auto i:d){
cout<<i<<endl; // 2,4
}
STL遍历删除标准写法
在你调用erase方法删除元素时,erase方法会返回下一个元素的迭代器,利用这一点,可以写这样的代码:
- vector+list+map的写法
for(vector<int>::iterator it=d.begin();it!=d.end(); )
if(*it==3)
it=d.erase(it);
it++;
}
map还能这样写:
for(vector<int>::iterator it=d.begin();it!=d.end(); )
if(*it==3)
d.erase(it++);