Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 就地删除图元的最佳方法_C++_Stl_Set - Fatal编程技术网

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());