从向量中删除对象的特定实例

时间:2013-10-28 22:45:07

标签: c++ vector stl erase

我有一个类Circle,我跟踪这些实例:

Circle *f1;
vector<Circle> list;
vector<Circle>::iterator it;

我设法创建了多个圈子并让它们四处移动。如何擦除Circle的特定实例?例如,如果某个圆圈撞到墙壁,则应该擦除它。我已经查看了其他问题,我甚至尝试了他们给出的代码而没有运气。这就是我现在所拥有的:

for (it = list.begin(); it != list.end(); ++it) {

    it->x += 1;

    if (it->x == ofGetWindowWidth()) {
        list.erase(it);
    }
}

我已经得到了其他声明来处理if语句,例如颠倒它们的移动方向。 list.erase(它);是我从这里得到的一行代码,我不明白为什么它会崩溃我的程序。

4 个答案:

答案 0 :(得分:4)

for (it = list.begin(); it != list.end(); /* nothing here */) {

    it->x += 1;

    if (it->x == ofGetWindowWidth()) {
        it = list.erase(it);
    } else {
        ++it;
    }
}

原始代码的问题在于擦除元素会使该元素的迭代器无效 - 您尝试接下来递增的迭代器也是如此。这表现出不确定的行为。

答案 1 :(得分:2)

list.erase使擦除元素的迭代器无效。因此,在擦除“it”指向的元素后,“it”无效,并且在for循环体之后的++ it会导致程序崩溃。 将代码重写为类似于以下内容的代码可以防止崩溃:

for(it=list.begin();it!=list.end(); ) {
    //your code
    if(it->x==ofGetWindowWidth())
        it=list.erase(it);
    else
        ++it;
}

答案 2 :(得分:2)

使用erase()的上述代码的问题在于,当元素被擦除时,它会使it的内容无效。您可以使用例如:

for (it = list.begin(); it != list.end(); ) {
    it->x += 1;

    if (it->x == ofGetWindowWidth()) {
        list.erase(it++);
    }
    else {
        ++it;
    }
}

使用erase()的分支在it元素之前将保留的迭代器erase()移离其当前位置。只有从it++返回的临时对象才会失效。当然,要使此循环起作用,您不能无条件地增加it,即非erase()分支需要自己的增量。

答案 3 :(得分:0)

您可以使用remove_if进行擦除。这也适用于删除多个元素。在你的情况下它是

list.erase(std::remove_if(list.begin(), list.end(),
        [](const Circle& c){return c.x == ofGetWindowWidth();},list.end()), 

整数示例:

#include <algorithm>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> str1 = {1,3,5,7};
    str1.erase(std::remove_if(str1.begin(), str1.end(),
                              [](int x){return x<4 && x>2;}), str1.end());
   for(auto i : str1) std::cout << i ;
}

打印157