容器list使用之erase

转自 : http://blog.sina.com.cn/s/blog_66f74d9f0100om0f.html


今天无论如何要写点东西,算是搞清楚了一点东西吧。有点小小的成就感。
             之 前在程序里面使用了list容器,其中用到了erase()函数 ,之前一直没出现问题,这两天突然莫名奇妙。花了点时间,搞清楚了erase()函数的机理。
             常用的删除容器中元素的方法是如下(方法1):
           list< int> List;
           list< int>::iterator iter;
           for( iter = List.begin(); iter != List.end(); )
           {
                       if(1)   
                       {
                              iter = List.erase( iter );
                       }
                       else
                       {
                             iter++;
                       }
           }

           也可以这样写(方法2):
           list< int> List;
           list< int>::iterator iter;
           for( iter = List.begin(); iter != List.end(); )
           {
                       if(1)   
                       {
                             List.erase( iter++ );
                       }
                       else
                       {
                             iter++;
                       }
           }

         有一种错误的写法(注意同方法2比较)
         list< int> List;
           list< int>::iterator iter;
           for( iter = List.begin(); iter != List.end(); )
           {
                       if(1)   
                       {
                             List.erase( iter );
                       }

                       iter++;
           }

         我们看一下erase()函数的源代码(仅列出release下的代码)。
               iterator erase(iterator _Where)
              {       // erase element at _Where
              _Nodeptr _Pnode = (_Where++)._Mynode();

              if (_Pnode != _Myhead)
                     {       // not list head, safe to erase
                     _Nextnode(_Prevnode(_Pnode)) = _Nextnode(_Pnode);
                     _Prevnode(_Nextnode(_Pnode)) = _Prevnode(_Pnode);
                     this->_Alnod.destroy(_Pnode);
                     this->_Alnod.deallocate(_Pnode, 1);
                     --_Mysize;
                     }
              return (_Where);
              }

函数在返回的时候,是返回当前迭代器的下一个节点。所以当 iter = List.erase( iter ); 执行以后,迭代器自动指向了下一个元素。而对于入参中的iter,所指的地址已经被销毁,所以写的时候,应该注意加上前面的iter =
那另外的一种写法,List.erase( iter++ ); 为什么也是对的呢?
这里研究了一下,这里需要讲一下++运算符的操作。(惭愧啊,++使用了这么多年,居然现在才搞明白)
             _Myt_iter& operator++()     
                     {       // preincrement
                     ++(*(_Mybase_iter *)this);
                     return (*this);
                     }

              _Myt_iter operator++(int) 
                     {       // postincrement
                     _Myt_iter _Tmp = *this;
                     ++*this;
                     return (_Tmp);
                     }

++实际上可以看做是一个函数。
对于++在后的情况(例如i++),函数在运行的时候,将运算的数据i已经改变,但是函数的返回值是操作之前的数据,所以在我们看来,i++好像是先进行了i的读取,才+1。

回到迭代器,List.erase( iter++ );就没有问题了。

对于那种错误的方法,List.erase( iter );在执行以后,iter所指的对象已经被销毁,所以再对iter进行操作是非法的,程序会出错。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值