【转载】用vector::erase对vector遍历删除

发布时间 2023-09-13 15:37:01作者: 朴实小码哥

在对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往后移动了一个位置,这样就不会发生错误。


原文链接:https://blog.csdn.net/Strengthennn/article/details/97645912