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

UIManager对象负责更新UILayouts的整个层次结构。每次对Update的调用都会在 vector mChildren上进行迭代,并递归地对每个 child 调用Update。

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

当我尝试从mChildren中删除所有也包含在mChildrenPendingRemoval中的条目时,出现异常。从UILayout::ResizeChildren():

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

IntersectsWithChildrenPendingRemoval的比较函数调用this-> ChildrenPendingRemovalContains(HUILayout ly),该函数执行以下操作:
return (find(mChildrenPendingRemoval.begin(), mChildrenPendingRemoval.end(),
    ly) != mChildrenPendingRemoval.end());

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

相关源代码:
  • Class and predicate definition
  • Implementation of the offending methods

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

    最佳答案



    您为什么不处理集合的拷贝,然后一次交换它:

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

    进一步的想法:
  • 通常,在任何时间段内都将迭代器保持在可变容器中并不是很方便
  • 既然这是智能指针的容器,那么... 如果需要保留元素的“指针”,为什么不将智能指针本身传递给呢? (当然,这不会启用迭代,但是无论如何,这不是IMO的健康要求)
  • 10-08 10:48