当比较来自单个向量的迭代器时,会引起什么'iterators are incompatible'?

What would provoke 'iterators are incompatible' when comparing iterators from one single vector?

本文关键字:什么 iterators incompatible are 单个 比较 向量 迭代器      更新时间:2023-10-16

我正在做一个UI。UI组件的基类是UILayout,整个UI是一个UILayout对象树,根是代表整个屏幕的UILayout。为了包含这个层次结构,任何给定的ui布局都有一个向量mChildren boost::shared_ptr<UILayout>

UIManager对象负责更新整个ui布局的层次结构。每次调用Update都会迭代vector mChildren,递归地对每个子类调用Update。

因为改变vector的形状会使这些迭代器失效,所以从mChildren中添加和删除条目仅限于ResizeChildren方法。当需要添加或删除组件时,它们被添加到两个向量之一,mChildrenPendingAddition和mChildrenPendingRemoval。在Update循环之前,ResizeChildren被调用,并相应地更新mChildren。(如果这是一个愚蠢的处理这个问题的方法,请阻止我。)

当我试图从mChildren中删除也包含在mChildrenPendingRemoval中的所有条目时,我得到了一个异常。从UILayout: ResizeChildren ():

mChildren.erase(remove_if(mChildren.begin(), mChildren.end(),
    IntersectsWithChildrenPendingRemoval(this)), mChildren.end());

IntersectsWithChildrenPendingRemoval的比较函数调用这个->ChildrenPendingRemovalContains(HUILayout ly),它做以下事情:

return (find(mChildrenPendingRemoval.begin(), mChildrenPendingRemoval.end(),
    ly) != mChildrenPendingRemoval.end());

那行有时调试断言vector迭代器不兼容失败。关于这个错误存在很多问题,但它似乎通常表明正在比较来自不同容器的两个迭代器。但在这里,显然不是这样的,对吧?还有什么可能导致这个问题?

相关源代码:

  • 类和谓词定义
  • 违规方法的实施

这是一个插件,我正在开发一个多线程应用程序。这个问题以非常罕见和随机的间隔出现的事实使我相信它与插件在单独的线程中运行的事实有关,但是所有这些方法都是从单个函数调用的,在单个线程中,并且mChildren不能在任何其他线程中访问或修改。

如果这是一个愚蠢的处理这个问题的方法,请阻止我

你为什么不做一个集合的副本,并立即交换它:

std::list<X> copy(mChildren);
copy.insert(...);
copy.remove(...);
copy.insert(...);
// at once:
std::swap(copy, mChildren);

进一步的想法:

  • 在任意一段时间内将迭代器保存在可变容器中通常不是很方便

  • 因为这是一个智能指针的容器…如果需要保留指向元素的指针,为什么不传递智能指针本身呢?(当然,这不会实现迭代,但在我看来,这不是一个非常健康的愿望)

使用索引代替迭代器。迭代器被高估了。它们只不过是一般的指针。在矢量中管理项的最佳方法一直是使用索引。如果你想使用迭代器,试试std::list,在这种情况下,即使你向列表中添加或删除元素,迭代器也不会失效。