在擦除()之后保持一个有效的向量::迭代器 [英] Keeping a valid vector::iterator after erase()

查看:18
本文介绍了在擦除()之后保持一个有效的向量::迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多答案告诉我应该将删除分离到另一个循环中.也许我说得不够清楚,但我在最后一段中说过,我想找到除此之外的解决方案.即保持当前的代码结构,但使用一些鲜为人知的 C++fu 使其工作.

I have had a lot of answers telling me that I should separate the deletion into another loop. Perhaps I did not make it clear enough, but I stated in my last paragraph that I'd like to find a solution OTHER than that. ie keeping the current code structure, but using some little-known C++fu to make it work.

好吧,我知道在向量上调用 erase() 会使该元素及其之后的所有迭代器无效,并且 erase() 会返回一个迭代器到下一个有效的迭代器,但是如果擦除发生在其他地方怎么办?

Well, I know that calling erase() on a vector invalidates iterators to the element and all those after it, and that erase() returns an iterator to the next valid iterator, but what if the erase happens elsewhere?

我有以下情况(简体):

I have the following situation (simplified):

警告:不要假设这是整个代码.下面显示的内容非常简化以说明我的问题.下面显示的所有类和方法实际上要复杂得多.

WARNING: Do NOT assume that this is the entire code. What is shown below is EXTREMELY simplified to illustrate my problem. All the classes and methods shown below are actually far more complex.

class Child {
   Parent *parent;
}

class Parent {
   vector<Child*> child;
}

void Parent::erase(Child* a) {
   // find an iterator, it, that points to Child* a
   child.erase(it);
}

int Child::update() {
   if(x()) parent.erase(*this) // Sometimes it will; sometimes (most) it won't
   return y;
}

void Parent::update() {
   int i = 0;
   for(vector<A>::iterator it = child.begin(); it != child.end(); it++)
      i += (*it)->update();
}

所以,很明显,如果 x() 返回 true,它会在运行 (*i​​t)->update() 后崩溃,因为当它运行时,Child 将告诉 Parent 将其从向量中删除,从而使迭代器无效.

So, obviously, it will crash after it runs (*it)->update() if x() returns true, because when it does, the Child will tell the Parent to remove it from the vector, invalidating the iterator.

除了让 Parent::erase() 将迭代器一直传递到 Parent::update() 之外,还有什么方法可以解决这个问题?这将是有问题的,因为不是每次调用 Child::update() 时都会调用它,因此该函数需要一种方法来每隔一次将迭代器返回给自身,它是目前还返回另一个值.我还希望避免使用其他类似的方式将擦除过程与更新循环分开.

Is there any way of fixing this other than making Parent::erase() pass an iterator all the way back up to Parent::update()? This would be problematic, as it is not called for every call to Child::update(), and thus that function would need a way to return an iterator to itself every single other time, and it is also currently returning another value. I would also prefer to avoid some other similar way to separate the erasing the process from the updating loop.

推荐答案

你不能真正地同时迭代和改变一个 std::vector,除非在迭代之间有一些通信改变.

You can't really iterate over and mutate a std::vector at the same time unless there's some communication between the iteration that the mutation.

我已经看到其他非标准容器通过智能"迭代器来促进这一点,这些迭代器知道它们的值何时被删除(并且可能会自动跳转到下一个项目).不过记账要多一些.

I've seen other, non-standard, containers facilatate this through "smart" iterators that know when their value has been erased (and maybe auto-jump to the next item). It's quite a bit more book-keeping though.

这篇关于在擦除()之后保持一个有效的向量::迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆