在迭代向量时,建议的避免错误的方法有哪些;向量中的任何数量的元素可能(直接地或间接地)导致元素的插入或删除 - 使迭代器无效?
具体来说,我要求与游戏编程有关,向量中的元素是游戏对象;其中一些可以产生其他对象,其中一些将被杀死,并在更新时需要删除。因此,在迭代之前保留大容量也是不可能的,因为完全不知道可以添加多少元素。
答案 0 :(得分:3)
一般来说,这是不可能的。迭代器失效的原因的部分是没有办法读懂你的想法,知道你希望失效的迭代器引用哪个元素。
例如,我有一个5的元素3的迭代器。我擦除元素2.迭代器是否指向新元素2(因为它是“向下移动的相同值”),或者它应该指向新元素3(因为它是“具有不同值的向量的相同元素向下移动”)?
实际上,您的选择是:
std::list
将为您提供上面的第一个选项(“迭代器引用新位置中的相同元素”)您用于迭代的迭代器永远不会因该位置的单个元素的插入/擦除而无效。它无效,但两个函数都返回一个可用于继续迭代的新迭代器。请参阅他们的文档,了解新迭代器引用的元素。这就是为什么只有当你在同一个容器上使用多个迭代器时才会出现这个问题。
答案 1 :(得分:1)
Vector可能不是支持密集插入/删除的最佳容器(特别是当大小很大时)。 但是如果你必须使用向量,恕我直言,最安全的方法是不使用迭代器而是使用索引并在当前位置之前跟踪(并调整索引)正在插入/删除的项目。这样您至少可以避免重新分配的问题。
每次迭代后重新计算v.size()/ v.end()。
答案 2 :(得分:1)
以下是一些想法:
答案 3 :(得分:0)
使用单独的向量和std::move
不会被删除的元素以及任何创建的新元素。然后放下旧矢量。
这样您就不必从原始向量中移除/插入任何内容,并且迭代器不会失效。
答案 4 :(得分:0)
当然,您可以使用一个容器来解决问题,该容器在插入和删除时不会使迭代器失效。
我想推荐一种不同的方法。基本上你是在迭代矢量来创建游戏世界中的新状态。在遍历矢量时,不是改变世界的状态,而是在新的矢量中存储需要改变的东西。然后,在完全检查旧状态后,应用存储在新矢量中的更改。
这种方法有一个概念上的优势:每个对象的新状态都取决于旧状态仅。如果在遍历旧状态时应用更改,并且有关一个对象的决策可能依赖于其他对象,则遍历的顺序可能会影响结果,这会使“早期”或“更晚”的对象成为不公平的优势。