白云哥

身披半件长工衣,怀揣一颗地主心

 
@cexer

http://www.cplusplus.com/reference/stl/vector/erase/

这里是一个比较好的描述

“Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions”

“This invalidates all iterator and references to elements after position or first.”


删除对象后会让迭代器之后的对象移动,因此而导致迭代器失效


map的实现,红黑树,在插入和删除对象后因为要做平衡,所以同样也有可能导致迭代器的失效


当然最终是不是会出现迭代器错误,这依赖于标准库的具体实现,另外还可能包括其优化方法
@cexer

是的,这个依赖于标准库的实现
我用vs2010会出现迭代器失效,程序立即终止
在mac os下用gcc没有问题


但这个确实是有问题的,标准里是否有相关描述我不是很清楚,但是可以看这里,别人介绍的方法也是我上面说的


http://stackoverflow.com/questions/1038708/erase-remove-contents-from-the-map-or-any-other-stl-container-while-iterating

总之是不能用“先保存迭代器,再删除”的方法,因为在删除的时候“有可能”会导致迭代器失效

看起来确实是“有可能”,这依赖于具体的实现 :)
@cexer

“在循环中保存下一个迭代器的方法:对于删除操作是没有任何问题的”
这个确定是有问题的,我就是好几次遇到了这样的问题才写的这个总结

下面是根据你的方法写的测试程序,运行一下,删除容器的第一个数据后,原来的迭代器就失效了


#include <vector>
#include <iostream>

typedef std::vector<int> container_type;
container_type m_container;

void do_remove(container_type::iterator itr)
{
m_container.erase(itr);
}

int main()
{
for (int i = 0; i < 100; ++i)
{
m_container.push_back(i);
}

container_type::iterator it_this = m_container.begin();
container_type::iterator it_next;
while (it_this != m_container.end())
{
it_next = it_this;
++it_next;

do_remove(it_this);

it_this = it_next;
}

return 0;
}
@cexer


做删除标志是一个方法,但对于对象有可能在其他地方已被删除的情况将没法实用(在这种情况下我的例子里的代码同样也有问题)

另外,在while循环中删除对象,虽然临时保存了下一个迭代器指针,这个同样是有问题的.因为删除容器对象有可能使得之前所保存的迭代器全都失效

如果要用删除标志,这样是可行的:

for(container::iterator itr = container.begin(); itr != container.end(); )
{
if (itr->second->is_dirty())
itr = container.erase(itr);
else
++itr;
}
@黑色灵猫

受教,目前在使用FXComposor时用到了这个,不得不对这多些了解。或许MS将这个标准废除是有理由的,Nvidia的FXComposor需要这样一种方法也是确定的,所以,DXSAS变成了SAS
模板用的很精彩,学习
这个libevent的vs2005包很好,谢谢

自己偷懒了一把 :)

导航

统计

常用链接

留言簿(4)

随笔分类

随笔档案

相册

我的链接

搜索

最新评论

阅读排行榜

评论排行榜