STL的erase()陷阱

本文的目的
    erase在删除容器中的元素时,由于迭代器失效会产生严重的错误;本文不讲太多的废话,直接从erase的使用性角度,总结了erase的通用使用套路,便于以后程序的开发。


容器分类
  常见的容器有2大类,分别是:
      节点式容器:(map, list, set)
      顺序式容器:(vector,string,deque)


erase & 顺序式容器
    在使用顺序式容器(vector,string,deque)遍历删除元素时,通常使用erase的返回值获取已删除元素的下一个元素的迭代器位置,保证迭代器不失效。
① 错误的代码

std::vector<struct> mFriendVec;
...
std::vector<struct>::iterator iter = mFriendVec.begin();
for ( std::vector<struct>::iterator iter = mVector.begin(); 
      iter != mFriendVec.end(); 
      ++iter
      )
{
    if (  willDelete(*iter)  )  // if若成立,程序肯定崩溃,为什么呢?
        mFriendVec.erase(iter);
}

② 正确的代码

std::vector<struct> mVector;
...
for ( std::vector<struct>::iterator iter = mVector.begin(); 
      iter != mVector.end(); 
      )
{
    if (  willDelete(*iter)  )  // 如果是待删除元素
    {
        //顺序式容器会使本身和后面的元素迭代器都失效,所以不能简单的++操作
        iter = mVector.erase(iter); //erase返回值 = 指向已删除元素的下一个元素的iterator
    }
    else  
    {
        ++iter; 
    }
}

erase & 节点式容器
    总结:无论是 节点式容器 还是顺序式容器 ,在对迭代器iter进行删除时,我们都使用通用的万能公式,代码见下。

std::list<int> List;
std::list<int>::iterator iter;
for( iter = List.begin(); iter != List.end(); )
{
      if( WillDelete( *iter ) )
      {
            iter = List.erase(iter);  //保存iterd的下一个元素
       }
       else
            iter++;
}

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/91855683