c ++如何在内部循环中使用带有auto的向量擦除对象

时间:2016-03-05 11:10:02

标签: c++ pointers for-loop vector auto

嗨大家好,在stackoverflow,

我一直想知道是否有任何简单的方法:迭代器控制范围for-loops 在访问时从容器内正确擦除对象;使用自动它。

对于标准的索引控制for循环,我会这样做:

void del(int i){
    cout<<"Deleting: "<<myObjects[i]<<':'<<myObjects[i]->c<<endl;
    for(unsigned int j = 0; j < allObjects.size();){
        if(allObjects[j] == myObjects[i]){
            delete allObjects[j];
            allObjects[j] = 0;
            allObjects.erase(allObjects.begin()+j);
            break;//Found and deleted first instance, escaping for-loop.
        }else{
            ++j;
        }
    }
    myObjects[i]=0;
    myObjects.erase(myObjects.begin()+i);
}

auto for循环看起来像这样:

void del(int i){
    cout<<myObjects[i]<<endl;
    for(auto it: allObjects)
        if(it == myObjects[i]){
            delete it;
            it = 0;
            //allObjects.erase();// Found, needs erasing.
        }
    myObjects[i]=0;
    myObjects.erase(myObjects.begin()+i);
}

我无法正确地解决这个问题,并且一直在使用旧式索引(很多方法都可以使用索引)。

我可以删除它,并将其设置为0,但是我如何从矢量中删除它,并且可能在矢量中而不知道索引?我知道我可以跟踪循环并使用计数器这样做,但是这会破坏使用漂亮的干净迭代器循环的目的。

如果不在向量中删除,除了重新访问向量之外,我将如何以一种简单的方式进行此类操作?

使用索引驱动的for循环没有错,只是想知道使用我们的新朋友“auto it”是否有一个简单的替代方案。

感谢。

3 个答案:

答案 0 :(得分:3)

对不起,但是没有办法使用基于范围的for循环来擦除。你应该使用标准方式:

for(auto it = allObjects.begin(); it != allObjects.end();)
{
    if(/* condition */)
        it = allObjects.erase(it);
    else
        ++it;
}

另见最新答案:Can we erase the items in range-based for loop in c++11

答案 1 :(得分:2)

您可以(并且应该)使用标准库,而不是滚动自己的循环:

allObjects.erase( std::remove(myObjects.begin(), myObjects.end, myObjects[i]),
                 allObjects.end() );

这更有效,因为您的算法是O(n ^ 2),因为元素一直在移位,并且它更具可读性。

在您的情况下,由于存储指针,您必须先删除“已删除的对象”:

auto r = std::remove(myObjects.begin(), myObjects.end, myObjects[i]);
for(auto i=r; i != allObjects.end(); ++i) {
     delete *i;
}
allObjects.erase(r, allObjects.end());

如果您使用智能指针(std:unique_ptrstd::shared_ptr),这将更简单,因为您可以跳过手动循环并只使用常见的单行。

答案 2 :(得分:0)

objects.erase(
    std::remove_if(
        objects.begin(),
        objects.end(),
        [](const Object &) -> bool {
            // Do "some stuff", then return true if element should be removed.
            return true;
        }
    ),
    objects.end()
);

您也可以使用Boost.Range和Lambda。