我有一组迭代的对象,但是我可以在迭代期间决定现在需要删除其中一个(或多个)对象.
我的代码如下:
if( ! m_Container.empty() ) { for( typedefedcontainer::iterator it = m_Container.begin(); it != m_Container.end(); ++it ) { if( ! ( SomeFunction( (*it), "test", "TEST!", false )) ) { // If function returns false, delete object. m_Container.erase( it ); AsyncResponseStore::iterator it = m_asyncResponses.begin(); } } }
但是当然,当我擦除一个对象时,我得到一个错误:"Map/set iterator not incrementable".有人可以建议一个更好的方法吗?
请参阅: 如果在从开始到结束迭代时调用map元素上的erase()会发生什么?
这取决于容器.列表容器支持在枚举期间删除,方法是从erase方法返回一个新的迭代器,该方法代表列表中的下一个项目.地图不支持此功能.
一种简单的map方法是在单独的列表中累积要擦除的项目,然后在完成地图处理以从地图中删除项目后迭代该列表.这假定您可以推迟删除,直到迭代完成.如果没有,那么你别无选择,只能为每次删除重新启动迭代.
如果容器支持它(我怀疑你的不支持,但问题标题是通用的,所以如果不是你这可能对其他人有用):
struct SomePredicate { bool operator()(typedefedcontainer::value_type thing) { return ! SomeFunction(thing, "test", "TEST", false); } }; typedefedcontainer::iterator it; it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate()); m_Container.erase(it, m_Container.end());
m_Container必须具有擦除范围方法,该方法包括任何序列或关联容器.它确实必须有一个可变的迭代器,我只是注意到我最初误读了错误信息:它说"map/set iterator not incrementable".所以我猜你的容器是一张地图或一套.
请注意,最后三个可能是一个真正奇妙的单行,但这个边距太窄,无法容纳它.
另外SomePredicate可以有一个带参数的构造函数来将其他参数存储到SomeFunction,因为在现实生活中我猜它们是非常量的.
如果你使用boost:bind来构造函数,你实际上可以完全摆脱SomePredicate.那么你的单行将真正庞大.
[编辑:Rob Walker在他的回答中正确地注意到我在这里做出的假设并且问题没有说明,即所有擦除都可以推迟到迭代测试完成之后.如果SomeFunction通过隐藏路由访问m_Container(例如全局,或者因为SomeFunction实际上是其成员函数),并且其结果取决于容器的内容,那么我的代码可能与提问者的代码不同.但我认为我的代码是"除非有理由不"默认.