原位删除元素的最佳方法

时间:2008-12-09 16:09:12

标签: c++ stl set

我有一组迭代的对象,但是我可以在迭代期间决定现在需要删除其中一个(或多个)对象。

我的代码如下:

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?

3 个答案:

答案 0 :(得分:6)

这取决于容器。列表容器支持在枚举期间删除,方法是从erase方法返回一个新的迭代器,该方法表示列表中的下一个项目。地图不支持此。

一种简单的map方法是在单独的列表中累积要删除的项目,然后在完成地图处理以从地图中删除项目后迭代该列表。这假定您可以推迟删除,直到迭代完成。如果没有,那么你别无选择,只能为每次删除重新开始迭代。

答案 1 :(得分:6)

如果容器支持它(我怀疑你的容器不支持,但问题标题是通用的,所以如果不是你这可能对其他人有用):

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实际上是其成员函数),并且其结果取决于容器的内容,那么我的代码可能与提问者的代码不同。但我认为我的代码是“除非有理由不”默认。]

答案 2 :(得分:0)

修正如下:

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;
    } 

}

删除元素时,所有指向它的指针都将失效。因此,通过使用它,我们可以解决它。感谢那些发布建议的人。