当比较来自单个向量的迭代器时,会引起“迭代器不兼容”的原因是什么?

时间:2011-11-29 22:01:56

标签: c++ multithreading stl iterator shared-ptr

我正在使用UI。 UI组件的基类是UILayout,整个UI是UILayout对象的树,其中根是表示整个屏幕的UILayout。为了包含此层次结构,任何给定的UILayout都有boost::shared_ptr<UILayout>的向量 mChildren

UIManager对象负责更新UILayouts的整个层次结构。每次调用Update都会迭代向量mChildren,以递归方式调用每个子进程的Update。

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

当我尝试从mChildren中删除mChildrenPendingRemoval中包含的所有条目时,我收到异常。来自UILayout :: ResizeChildren():

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

IntersectsWithChildrenPendingRemoval的比较函数调用this-&gt; ChildrenPendingRemovalContains(HUILayout ly),它执行以下操作:

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

该行有时未通过调试断言矢量迭代器不兼容。关于此错误存在大量现有问题,但似乎通常表明正在比较来自不同容器的两个迭代器。但在这里,情况显然不是这样,对吧?还有什么可能导致这个问题?

相关源代码:

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

2 个答案:

答案 0 :(得分:0)

  

如果这是处理这一特定问题的一种愚蠢方式,请阻止我

为什么不处理集合的副本,并立即交换它:

std::list<X> copy(mChildren);

copy.insert(...);
copy.remove(...);
copy.insert(...);

// at once:
std::swap(copy, mChildren);

进一步的想法:

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

  • 由于这是一个智能指针的容器... 如果你需要保留',你为什么不绕过 传递智能指针?指向元素的指针? (当然,这不会启用迭代,但这无论如何都是IMO不是一个非常健康的愿望)

答案 1 :(得分:-1)

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