剖析STL容器遍历删除时诡异的erase(iter++) http://bbs.csdn.net/topics/100044107
来源:互联网 发布:迅雷快鸟 mac 版本 编辑:程序博客网 时间:2024/06/05 00:14
剖析STL容器遍历删除时诡异的erase(iter++)
---------------------------------------------------------------------
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);
}
}
为什么呢?
以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++.
哪为什么m_list.erase(iter++)可以呢?为什么不能用m_list.erase(++iter)?
参照operator++的代码我们可以找到答案,iter++返回了++之前的iter值,erase使用这个值能正确进行__position的前后结点的串接及删除正确的结点,而++iter返回的是++之后的iter,所以m_list.erase(++iter)串接不正确,iter->_M_node也是失效的.
对于非结点类,如数组类的容器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,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);
}
}
为什么呢?
以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++.
哪为什么m_list.erase(iter++)可以呢?为什么不能用m_list.erase(++iter)?
参照operator++的代码我们可以找到答案,iter++返回了++之前的iter值,erase使用这个值能正确进行__position的前后结点的串接及删除正确的结点,而++iter返回的是++之后的iter,所以m_list.erase(++iter)串接不正确,iter->_M_node也是失效的.
对于非结点类,如数组类的容器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;
}
0 0
- 剖析STL容器遍历删除时诡异的erase(iter++) http://bbs.csdn.net/topics/100044107
- 剖析STL容器遍历删除时诡异的erase(iter++)
- 剖析STL容器遍历删除时诡异的erase(iter++)
- STL容器遍历删除时诡异的erase
- STL容器遍历删除时诡异的erase
- window遍历文件夹下的文件 http://bbs.csdn.net/topics/390368005/
- STL容器的遍历删除操作erase
- http://bbs.csdn.net/topics/390626193的最后解决办法。
- 很有用的算法http://bbs.csdn.net/topics/390768965
- vector 扩展的时候http://bbs.csdn.net/topics/260070400
- 多态的实现:http://bbs.csdn.net/topics/370166353
- http://bbs.csdn.net/topics/390281904有感
- http://bbs.csdn.net/topics/390336687
- http://bbs.csdn.net/topics/360205599
- http://bbs.csdn.net/topics/320159639
- http://bbs.csdn.net/topics/390025630
- http://bbs.csdn.net/topics/370159572
- http://bbs.csdn.net/topics/350058815
- “FileLoadException was unhandled”解决方法
- socket连接池SocketPool分析(二):《UNPv1》复习(上):socket函数,三次握手,四次挥手
- IOS UI 01 课堂笔记 -label
- table表格序列化
- socket连接池SocketPool分析(三):《UNPv1》复习(下):IO多路复用
- 剖析STL容器遍历删除时诡异的erase(iter++) http://bbs.csdn.net/topics/100044107
- 磁盘、分区、卷详解cmd命令
- socket连接池SocketPool分析(四):socket连接控制SocketObj
- java实现梯度下降算法
- 11、osg中的粒子系统所用到的类以及相关函数
- BF算法(java版本)
- Linux下头文件搜索路径
- socket连接池SocketPool分析(五):Accept函数,进退维谷的困境
- 第13周项目2-Kruskal算法的验证