从循环中的列表中删除元素而不中断

时间:2011-09-06 19:12:22

标签: c++

在我的游戏代码中,我想从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;
    }
}

提前谢谢!

编辑: 对不起,我对矢量和列表很困惑。得到了答案,谢谢!

4 个答案:

答案 0 :(得分:8)

你应该这样做:

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

}

答案 1 :(得分:0)

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

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

使用向量在中间擦除速度很慢,并且还使所有迭代器和引用无效。

答案 2 :(得分:0)

过滤掉标准库容器中的项目的正确方法是使用Erase-Remove Idiom。因为您在循环中使用成员函数作为测试,所以您应该调整示例以使用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<>等,无论实现和迭代器失效语义如何。

修改:我发现你在循环中也使用了Arrow::update()方法。您可以在列表上执行双遍,使用函数对象来调用这两个方法或手动编写循环。

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

答案 3 :(得分:0)

就像所有人都说你的例子令人困惑。如果要在容器中间删除,并且使用

1&GT;矢量: 然后擦除点之后的每个迭代器和引用都无效。 另外,从向量中间删除向量将导致其后面的元素移位,如果你想要性能,可能会认为它很慢。

2 - ;列表: 然后只有删除的迭代器和引用无效。

当您想删除stl序列容器中间的某个元素时,首选使用erase-remove idiom