C++ 就地删除图元的最佳方法
我有一组迭代的对象,但是在迭代过程中,我可能会决定现在需要删除其中一个(或多个)对象 我的代码如下:C++ 就地删除图元的最佳方法,c++,stl,set,C++,Stl,Set,我有一组迭代的对象,但是在迭代过程中,我可能会决定现在需要删除其中一个(或多个)对象 我的代码如下: if( ! m_Container.empty() ) { for( typedefedcontainer::iterator it = m_Container.begin(); it != m_Container.end(); ++it ) { if( ! ( Some
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迭代器不可递增”。有人能提出更好的方法吗
见:
这取决于容器。列表容器通过从表示列表中下一项的erase方法返回新的迭代器来支持枚举期间的删除。地图不支持这个
映射的一个简单方法是将要删除的项累积到一个单独的列表中,然后在处理完映射后在该列表上迭代以从映射中删除这些项。这假设您可以推迟删除,直到迭代完成。如果没有,则您别无选择,只能为每次删除重新启动迭代。通过以下方式修复:
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++我们可以绕过它。感谢那些发表建议的人。如果容器支持它(我怀疑您的容器不支持,但问题标题是通用的,因此如果您不支持,这可能对其他人有用): m_容器必须具有擦除范围方法,该方法包括任何序列或关联容器。不过,它必须有一个可变迭代器,我只是注意到我最初误读了错误消息:它说“map/set iterator not incrementable”。所以我猜你的容器是一张地图或一套 请注意,最后三个可能是一个真正奇妙的一行,但这个空白太窄,无法容纳它 还有,SomePredicate可以有一个带参数的构造函数来存储SomeFunction的附加参数,因为在现实生活中,我猜它们是非常量的 如果使用boost:bind来构造函子,实际上可以完全摆脱SomePredicate。你的一艘邮轮将是真正的巨大
[编辑:Rob Walker在他的回答中正确地指出了我在这里提出的一个假设,问题没有说明,即所有擦除都可以推迟到迭代和测试完成之后。如果SomeFunction通过隐藏路径访问m_容器(例如,全局,或者因为SomeFunction实际上是此函数的成员函数),其结果取决于容器的内容,那么我的代码可能与提问者的代码不相等。但我认为我的代码是“除非有理由不”默认值。]仅仅因为您安全地前进到下一个迭代器,并不意味着该迭代器是有效的。一个接一个是最好的解决方案。虽然对于某些容器类型,这确实意味着。正如罗伯·沃克所说,你能做什么取决于容器的类型。这就是为什么std::remove_(如果存在)的原因,因为它与erase一起作用于任何具有可变迭代器的对象。为什么要测试容器的空性?如果为空,则永远不会输入for循环。
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());