[STL]使用vector::erase对vector遍历删除

在对vector中的元素进行遍历删除时遇到了一点问题,查博客发现博客上并不靠谱。在此记录,共同进步。
vector循环遍历正确代码:

  for(vector<int>::iterator it=vec.begin(); it!=vec.end();){
        if(*it == 3){
            vec.erase(it);
        }else{
            it ++;
        }
    }

或者:

  for(vector<int>::iterator it=vec.begin(); it!=vec.end();){
        if(*it == 3){
            it = vec.erase(it);
        }else{
            it ++;
        }
    }

推荐使用第二种。因为vector::erase()的实质是将迭代器后面的元素全部复制一遍,往前移动一个位置,可以查看erase()的源代码是:

  _M_erase(iterator __position)
    {
      if (__position + 1 != end())
        std::copy(__position + 1, end(), __position);
      --this->_M_impl._M_finish;
      return __position;
    }

所以如果遇到erase(it + 1)这种情况使用第一种方案会出错,使用第二种不会。
原因如下:

此时使用erase(it+1)会出错是因为:在erase()方法的源代码中可以看出:使用erase(it+1)时_M_erase(iterator
__position)方法输入的参数为__position,指向的位置为it+1处。该方法的操作为:将__position之后的数据向前移动一个位置。移动之后,__position位置处的数据就变成了原来的__position+1处的数据,__position+1处的数据变成原来__position+2处的数据,以此类推。但移动之后it指向的位置和it处的数据值都没有改变,而且for循环中没有对it进行++(自增)的操作,这样*it就一直等于3,会一直执行erase(),将vector中在(*it==3)之后的所有数据都删除。
而it = erase(it+1)时,erase()方法执行后it被赋值为改变后的__position(前文中加粗的__position),相当于it往后移动了一个位置,这样就不会发生错误。

另外,我查别人的博客时发现有人说不能使用如下代码(下面这个代码是错的):

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++)
{
      if( *iter == 3)
             veci.erase(iter);
}

是因为会使it变成野指针,其实并不是这个原因。这段代码之所以错是因为假如有两个连续的元素需要删除会漏删一个,例如需要删除[1,2,3,3,4]中的3时,上述代码只能删掉第一个3;而且假如被删除的元素是vector的最后一个元素时会出现野指针。

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值