STL容器在遍历时迭代器失效问题

转载自:https://blog.csdn.net/hechao3225/article/details/55101344
其他文章:https://www.cnblogs.com/qiaoconglovelife/p/5370396.html

STL容器根据迭代器的失效问题,其实可以分为两类容器:

(1)数组型容器的插入删除操作:vector、string、deque(均为顺序存储)
        由于这类容器的插入或删除都会使所有迭代器失效,因此每次插入删除后都需要重新定位

(2)结点型数据容器的插入删除操作:list(使用链表存储)、map(使用红黑树存储)、set(使用红黑树存储)
        由于这类容器删除时只会失效当前迭代器,而插入时不会使任何迭代器失效, 因此插入时不需重新定位,但是删除时需重新定位

一、遍历删除

为追求操作统一,两类容器在删除元素时每次都重新定位,即:
每次条件满足需要删除时,获取删除后返回的迭代器,而返回的迭代器直接指向了下一个位置,因此迭代器不用另外自增操作。
对于不满足条件时,需要迭代器另外自增操作,以保证循环正常进行,否则将进入死循环。

    //vector示例第一类容器
    vector<string> vec_str={"hello","hi","world"};
    auto it=vec_str.begin();
    while(it!=vec_str.end()){
        if(it->size()==5)//指定位置删除示例
            it=vec_str.erase(it);//返回的it自动指向下一个位置
        else
            it++;//未删除应移到下一个位置,否则陷入死循环
    }
    for(auto e:vec_str)
        cout<<e<<endl;
    vec_str.clear();
    //map示例第二类容器
    map<int,int> map_values;
    for(int i=0;i<5;i++){
        map_values.insert(pair<int,int>(i,i));
    }
    auto iter=map_values.begin();
    while(iter!=map_values.end()){
        if((iter->first)%2==0){//指定位置删除示例
            iter=map_values.erase(iter);//返回的it指向下一个位置
        }
        else
            iter++;
    }
    for(auto e:map_values){
        cout<<e.first<<" "<<e.second<<endl;
    }
    map_values.clear();

二、遍历插入

首先第二类容器在插入时不会使任何迭代器失效,因此循环插入时不存在问题。
但是第一类容器存在迭代器失效问题,由于vector和list容器的插入操作都是前插,并且返回指向插入后的元素的迭代器,如果每次重新定位到下一个元素,需要向前进两个位置!因此每次重新定位比较麻烦,并且vector插入效率低下,使用list替换vector,避开迭代器失效问题是最佳选择。
注意不要妄想使用insert向map或set的指定位置插入元素,map和set都是有序容器(底层是RBT),因此插入后map会自动按key排序元素,而set会自动排序元素,因此遍历时向指定位置(迭代器位置)插入的需求不会发生在map,如果发生了请考虑重新选择容器。

 //vector示例第一类容器(list作为中间容器示例第二类容器)
    vec_str.push_back("hello");
    vec_str.push_back("hi");
    vec_str.push_back("world");
    list<string> list_str;
    list_str.resize(vec_str.size());//resize必须,否则copy越界
    copy(vec_str.begin(),vec_str.end(),list_str.begin());
    for(auto it1=list_str.begin();it1!=list_str.end();it1++){
        if(it1->size()==5)
            list_str.insert(it1,"test");//直接插入,迭代器不会失效
    }
    vec_str.resize(list_str.size());//resize必须,list_str大小已变,否则copy越界
    copy(list_str.begin(),list_str.end(),vec_str.begin());
    for(auto e:vec_str){
        cout<<e<<endl;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值