stl中map的erase方法(转)
时间:2010-07-18 来源:GilBert1987
转:http://exrange.spaces.live.com/blog/cns!8ab404848776b052!231.entry
循环中使用erase删除map中的元素的时候 1.错误写法 int nFinishedCount = 0;
for( WSIter iter = m_ws.begin(); iter != m_ws.end(); ++iter )
{
SchdWorkSheet * pws = iter->second;
if( pws->completeWorkSheet() )
{
destroyWorkSheet(pws);
m_ws.erase(iter);
nFinishedCount++;
}
}
原因是迭代器的++操作的内部实际都是在操作它保存的节点指针(SGI STL Map的实作应该是红黑树(STL源码剖析)),所以当这个节点被删除的时候,该节点指针指向的内存的数据是无法确定的,也就是可能还是以前正确的数据,也可能已经是其他毫无相关的数据了,这样的行为也就是经常听说的undefined behavior.所以自然出现了,有时候还能正常运行一会儿,有时候就core掉了的情况,果然是undefined...
对于其他的链式存储,都是类似的解释感谢侯捷的《STL源码剖析》,对iterator有了重新理解,实在是好书...
2006 6.15
解决的办法是在删除iter指向的内容之前就将其移动到下一个正确地址,所以正确写法如下:
1.正确写法
int nFinishedCount = 0;
for( WSIter i = m_ws.begin(); i != m_ws.end(); )
{
SchdWorkSheet * pws = i->second;
if( pws->completeWorkSheet() )
{
destroyWorkSheet(pws);
m_ws.erase(i++);
nFinishedCount++;
}
else
++i;
}
不止是map, 链式存储结构的stl容器都会这样,而对vector. string连续存储来说,就删除一个元素的时候不需要将迭代器++了.
循环中使用erase删除map中的元素的时候 1.错误写法 int nFinishedCount = 0;
for( WSIter iter = m_ws.begin(); iter != m_ws.end(); ++iter )
{
SchdWorkSheet * pws = iter->second;
if( pws->completeWorkSheet() )
{
destroyWorkSheet(pws);
m_ws.erase(iter);
nFinishedCount++;
}
}
原因是迭代器的++操作的内部实际都是在操作它保存的节点指针(SGI STL Map的实作应该是红黑树(STL源码剖析)),所以当这个节点被删除的时候,该节点指针指向的内存的数据是无法确定的,也就是可能还是以前正确的数据,也可能已经是其他毫无相关的数据了,这样的行为也就是经常听说的undefined behavior.所以自然出现了,有时候还能正常运行一会儿,有时候就core掉了的情况,果然是undefined...
对于其他的链式存储,都是类似的解释感谢侯捷的《STL源码剖析》,对iterator有了重新理解,实在是好书...
2006 6.15
解决的办法是在删除iter指向的内容之前就将其移动到下一个正确地址,所以正确写法如下:
1.正确写法
int nFinishedCount = 0;
for( WSIter i = m_ws.begin(); i != m_ws.end(); )
{
SchdWorkSheet * pws = i->second;
if( pws->completeWorkSheet() )
{
destroyWorkSheet(pws);
m_ws.erase(i++);
nFinishedCount++;
}
else
++i;
}
不止是map, 链式存储结构的stl容器都会这样,而对vector. string连续存储来说,就删除一个元素的时候不需要将迭代器++了.
相关阅读 更多 +