它是在所有可能从载体擦除使用C ++ 11的for循环?(Is it at all possible

2019-10-20 03:47发布

好的。 对于其他(更简单,但没有足够的解释性)问题的缘故,这可能看起来像,我不问,如果这是可能的或不可能的(因为我发现的话),我问如果有一个打火机替代我题。

我有什么会被认为是一个主类,并在主类,有一个变量,它的“世界地图”类的引用。 从本质上说,这个“世界地图”类是其他类变量的容器。 Main类的循环的所有,并更新所有现用的各个对象的。 有在此循环次,我需要删除是深递归组容器的内部(如在提供的代码示出)的向量的对象。 这将是非常乏味的反复必须引用必要的变量作为一个指针到另一个指针(等)以指向特定对象我需要,后来删除它(这是我切换到C之前所使用的概念++ 11)所以代替我有循环的范围内(也示于代码)。 我的示例代码显示的想法,我在的地方,在这里我要削减的单调乏味,以及使代码更大量的可读性。

这是示例代码:

struct item{
    int stat;
};

struct character{
    int otherStat;
    std::vector<item> myItems;
};

struct charContainer{
    std::map<int, character> myChars;
};

int main(){
    //...
    charContainer box;
    //I want to do something closer to this
    for(item targItem: box.myChars[iter].myItems){
        //Then I only have to use targItem as the reference
        if(targItem.isFinished)
            box.myChars[iter].myItems.erase(targItem);
    }
    //Instead of doing this
    for(int a=0;a<box.myChars[iter].myItems.size();a++){
        //Then I have to repeatedly use box.myChars[iter].myItems[a]
        if(box.myChars[iter].myItems[a].isFinished)
            box.myChars[iter].myItems.erase(box.myChars[iter].myItems[a]);
    }
}

TLDR:我想删除的重复调用通过使用新的范围,适用于C ++ 11所示回路的完整参考乏味。

编辑 :我不是想一次全部删除的元素。 我问我怎么会删除他们在第一循环的问题。 我删除它们时,我与他们外部进行(通过if语句)。 我将如何删除特定的元素,不是所有的人?

Answer 1:

如果你只是想清除的std ::向量,就可以用一个很简单的方法:

std::vector<item> v;

// Fill v with elements...

v.clear(); // Removes all elements from v.

除了这一点,我想指出的是,[1],以擦除一个向量的元素,需要迭代器的使用,并且即使被允许[2]你的方法,擦除从载体元件内部的for循环一个糟糕的主意,如果你不小心。 假设您的载体有5个要素:

std::vector<int> v = { 1, 2, 3, 4, 5 };

然后,你的循环将具有以下效果:

  • 第一次迭代: a == 0, size() == 5 。 除去第一个元素,则载体将含有{2, 3, 4, 5}

  • 第二次迭代: a == 1, size() == 4 。 然后除去第二元件,则载体将含有{2,4,5}

  • 第三次迭代: a == 2, size() == 3 。 我们删除第三个元素,而我们只剩下最后的结果{2,4}

由于这实际上并没有清空矢量,我想这是不是你所期待的。

相反,如果你有,你想申请删除元素一些特定的条件,则很容易在C ++ 11通过以下方式应用:

std::vector<MyType> v = { /* initialize vector */ };

// The following is a lambda, which is a function you can store in a variable.
// Here we use it to represent the condition that should be used to remove
// elements from the vector v.
auto isToRemove = [](const MyType & value){ 
    return /* true if to remove, false if not */ 
};

// A vector can remove multiple elements at the same time using its method erase().
// Erase will remove all elements within a specified range. We use this method 
// together with another method provided by the standard library: remove_if.
// What it does is it deletes all elements for which a particular predicate 
// returns true within a range, and leaves the empty spaces at the end.
v.erase( std::remove_if( std::begin(v), std::end(v), isToRemove ), std::end(v) );

// Done!


Answer 2:

我删除它们时,我与他们外部进行(通过if语句)。 我将如何删除特定的元素,不是所有的人?

在我看来,你看这个错误的方式。 编写循环,从一个序列容器中删除项目始终是有问题的,不建议使用。 力争从以这种方式删除的项目望而却步。

当您使用的容器,您应该战略性地设置您的代码,这样您将删除或“要被删除”以易于访问的容器的一部分项目,远离容器内的项目,你不想删除。 那时的你其实想删除他们,你知道他们在哪里,因此可以调用一些功能从容器驱逐他们。

一个答案是已经给的,那就是使用erase-remove(if)成语。 当你调用removeremove_if ,是“坏”的项目被移动到容器的末尾。 返回值remove(_if)是迭代器将要删除的项目的开始。 然后你给这个迭代器的vector::erase方法从容器永久删除这些项目。

另一种解决方案(但可能较少使用)是std::partition算法。 该std::partition还可以将“坏”的项目到容器的结束,但不像remove(_if)项目仍然有效(即你可以在容器结束后离开他们,仍安全地使用它们) 。 再后来,当你在一个单独的步骤希望,因为你可以删除它们std::partition也返回迭代器。



Answer 3:

为什么没有对载体的标准迭代器迭代。 这样,你可以通过传递一个迭代器删除元素。 然后.erase()将返回下一个可用的迭代器。 如果你的下一个迭代器迭代器::结束(),那么你的循环将退出。



文章来源: Is it at all possible to erase from a vector with C++11's for loops?