STL中结点类容器(如:list,hash_map)遍历时进行删除时,需要这样做: 
for(list <int> ::iterator   iter   =   m_list.begin();   iter   !=   m_list.end();   ) 

        if(需要删除) 
        { 
                m_list.erase(iter++); 
        } 
        else 
                ++iter; 


而不能这样: 
for(list <int> ::iterator   iter   =   m_list.begin();   iter   !=   m_list.end();   ++iter) 

        if(需要删除) 
        { 
                m_list.erase(iter); 
        } 

对于非结点类,如数组类的容器vector,string,deque,如果erase会返回下个有效的iterator,可以这样处理: 
for(vector <int> ::iterator   iter   =   m_vector.begin();   iter   !=   m_vector.end();) 

        if(需要删除) 
        { 
                iter=m_vector.erase(iter); 
        } 
        else 
                ++iter; 
}



为什么呢? 

以STL   list为例: 

iterator的相关操作 
_Self&   operator++() 

        this-> _M_incr(); 
        return   *this;     


_Self   operator++(int) 
{         _Self   __tmp   =   *this; 
        this-> _M_incr(); 
        return   __tmp;                               //后缀++按照语意返回了++前的iterator, 


void   _M_incr()   {   _M_node   =   _M_node-> _M_next;   }         //++的操作对于list结构来说,就是使iterator的_M_node指向下一个结点 

iterator   erase(iterator   __position) 
{       _List_node_base*   __next_node   =   __position._M_node-> _M_next; 
        _List_node_base*   __prev_node   =   __position._M_node-> _M_prev; 
        _Node*   __n   =   (_Node*)   __position._M_node; 
        __prev_node-> _M_next   =   __next_node; 
        __next_node-> _M_prev   =   __prev_node;     //上面的代码把删除结点__position的前后结点串起来,而移除_positoin 
        _STLP_STD::_Destroy(&__n-> _M_data);   //call   T::~T() 
        this-> _M_node.deallocate(__n,   1);                         //释放结点内存 
        return   iterator((_Node*)__next_node); 
}   

分析代码我们可以看出,erase会deallocate__position的_M_node,   在__position上再进行++是错误的。 

所以不能在m_list.erase(iter)后,进行iter++. 

PS:erase后再++在VS下是必然报错的,在xcode下有时候会正常。


哪为什么m_list.erase(iter++)可以呢?为什么不能用m_list.erase(++iter)? 
参照operator++的代码我们可以找到答案,iter++返回了++之前的iter值,erase使用这个值能正确进行__position的前后结点的串接及删除正确的结点,而++iter返回的是++之后的iter,所以m_list.erase(++iter)串接不正确,iter-> _M_node也是失效的. 


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐