我有一组要迭代的对象,但是在迭代期间,我可能会决定现在需要删除这些对象中的一个(或多个)。
我的代码如下:
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“。有没有人能推荐一种更好的方法呢?
请参阅:What happens if you call erase() on a map element while iterating from begin to end?
发布于 2008-12-09 16:18:09
这取决于容器。列表容器通过从erase方法返回表示列表中下一项的新迭代器来支持枚举期间的删除。map不支持这一点。
map的一个简单方法是将要擦除的项目累积到一个单独的列表中,然后在完成对map的处理后遍历该列表以从map中擦除这些项目。这假设您可以将删除操作推迟到小版本完成。如果不是,那么您别无选择,只能在每次删除时重新启动迭代。
发布于 2008-12-09 16:39:51
如果容器支持它(我怀疑你的容器不支持它,但问题标题是通用的,所以这可能对其他人有用,如果不是你的话):
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通过隐藏路由(例如全局,或者因为SomeFunction实际上是它的成员函数)访问m_Container,并且其结果取决于容器的内容,那么我的代码可能不等同于提问者的代码。但我认为我的代码是默认的“除非有理由不这样做”。
发布于 2008-12-09 16:30:45
已通过以下方式修复:
for( typedefedcontainer::iterator it = m_Container.begin();
it != m_Container.end();
)
{
if( ! ( SomeFunction( (*it), "test", "TEST!", false )) )
{
// If function returns false, delete object.
m_Container.erase( it++ );
}
else
{
++i;
}
}当一个元素被删除时,所有指向它的指针都会失效。因此,通过使用it++,我们可以绕过它。感谢那些发表建议的人。
https://stackoverflow.com/questions/353296
复制相似问题