在循环中不间断地从list中删除元素

Remove elements from list in a loop without break

本文关键字:list 删除 元素 循环 不间断      更新时间:2023-10-16

在我的游戏代码中,我想从list中删除一些元素,
这在循环中发生。唯一的问题是,当我使用
时我必须在这个函数之后中断list::erase因为我认为
list变得"过时"。这会导致闪烁,我想要
试着删除它

当前代码是:

for(list<Arrow*>::iterator it = arrows.begin(); it != arrows.end(); it++)
{
    Arrow* a = (*it);
    if(a->isActive() == true)
    {
        a->update();
    }
    else
    {
        arrows.erase(it);
        break;
    }
}

提前感谢!

编辑:抱歉,我把向量和列表搞混了。知道答案了,谢谢!

你应该这样做:

it = arrows.erase(it);

//

list<Arrow*>::iterator it = arrows.begin();
while (it != arrows.end())
{
  Arrow* a = (*it);
  if(a->isActive())
  {
    a->update(); ++it;
  }
  else{ // delete (a); ???
   it=arrows.erase(it);}
}

我很困惑,你说矢量,在你的例子中你使用的是列表。

List是用一个双链表实现的(实际上它很可能被实现,因为标准只是修复了复杂性,而不是细节)。擦除后的迭代器仍然有效。http://www.cplusplus.com/reference/stl/list/erase/

使用vector在中间擦除是缓慢的,并且会使所有迭代器和引用失效。

就像每个人都说你的例子令人困惑。如果你想在容器中间删除如果你使用

1>向量:然后擦除点之后的每个迭代器和引用都无效。此外,从vector的中间删除vector会导致它后面的元素移动,如果你想要性能,这可能会被认为是缓慢的。

2>列表:只有被删除的迭代器和引用失效。

当您想要删除stl序列容器中间的某些元素时,无论使用哪一种方法都是首选的。

在标准库容器中过滤掉项的正确方法是使用Erase-Remove习语。因为在循环中使用成员函数作为测试,所以应该调整示例以使用std::remove_if()

你可以用一种简洁的方式实现它(如果你喜欢函数式编程):

#include <algorithm>
#include <functional>
arrows.erase(std::remove_if(
    arrows.begin(), arrows.end(), std::mem_fun(&Arrow::isActive)
    ));

这将适用于std::vector<>, std::deque<>, std::list<>等,无论实现和迭代器无效语义如何。

Edit:我看到你也在循环内使用Arrow::update()方法。您可以对列表进行双重传递,使用函数对象调用这两个方法,或者手动编写循环。

在最后一种情况下,您可以使用it = arrows.erase(it);技巧,但这只对std::list<>有效。的循环将具有O(n^2)复杂度std::vector<>std::deque<>容器