在循环中不间断地从list中删除元素
Remove elements from list in a loop without break
在我的游戏代码中,我想从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<>
容器
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- 使用容器中元素的别名删除带有 std::list::remove 的元素是否正确?
- 如何通过存储在 std::list 中的指针删除对象?
- 通过引用从 std::list 中删除元素
- 为什么具有 list<struct type>::itrator 的 struct 不能通过 clear() 删除?
- 将 std::list<std::unique_ptr> 移动到向量中会尝试引用已删除的函数
- 如何从 std::list 中删除元素?
- 从 std::list 中删除 std::tuple
- std::list - 删除元素
- 在迭代器时从 std::list 中删除条目
- 在C++中有条件地删除Singly Linked List中的元素
- 从 std::list 中删除对象
- 不应该像这样从 stl::list 中删除进入无限循环
- std::list remove_if删除节点
- 有效地从 std::list 中删除最后一个元素
- (C++) list.error 方法和使用指针删除内存
- std::list.remove 正在调用析构函数,但不删除它
- 迭代时从 std::list 中删除
- 如何正确删除 std::list 中的指针
- 正在从Singly Linked Circular List中删除特定节点