1

我有一个类 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

4 回答 4

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

    it->x += 1;

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

您的原始代码的问题是擦除一个元素会使该元素的迭代器无效 - 您接下来尝试递增的迭代器是相同的。这表现出未定义的行为。

于 2013-10-28T22:58:46.897 回答
3

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;
}
于 2013-10-28T22:59:57.147 回答
2

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

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

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

分支 using在ing 元素之前erase()将保留的迭代器it从其当前位置移开。erase()只有返回的临时对象it++才会失效。当然,要让这个循环工作,你不能无条件地递增it,即非erase()ing 分支需要它自己的递增。

于 2013-10-28T23:00:02.793 回答
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

于 2013-10-28T23:06:12.120 回答