从矢量中擦除对象的特定实例

Erasing a specific instance of an object from a vector

本文关键字:实例 对象 擦除      更新时间:2023-10-16

我有一个类圈,我用这些实例跟踪它的实例:

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 语句一起使用,例如反转它们的运动方向。 列表.擦除(它); 是我从这里得到的一行代码,我不明白为什么它会让我的程序崩溃。

for (it = list.begin(); it != list.end(); /* nothing here */) {
    it->x += 1;
    if (it->x == ofGetWindowWidth()) {
        it = list.erase(it);
    } else {
        ++it;
    }
}

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

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;
}

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

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

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

您可以使用 擦除 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