为什么我得到错误'矢量迭代器不兼容'?

时间:2014-05-29 09:57:03

标签: c++ visual-c++ vector iterator std-function

我正在为我的程序编写一个小UI。我有方法onMouseMotion(),我可以用两种方式之一调用它(参见代码);如果我通过std::function调用它,那么for循环停止条件中的!=运算符会产生运行时异常vector iterators incompatible。为什么呢?

class Widget : public EventHandler
{
protected:
    /* ... */
    std::vector<Widget *> children_;                        
    std::function<bool(Event &)> func_;

private:
    bool onMouseMotion(Event &event);
    /* ... */   
};

Widget::Widget() 
{
    /* ... */
    func_ = std::bind(&Widget::onMouseMotion, this, std::placeholders::_1);
    /* ... */
}

bool Widget::processEvent(Event &event)
{
    if (event.getType() == ui::EventType::MouseMotionEvent) {

        /* Method 1 - onMouseMotion works ok */     
        onMouseMotion(event);

        /* Method 2 - onMouseMotion throws */
        //func_(event);

        return true;
    }
}

bool Widget::onMouseMotion(Event &event)
{
    /* exception occurs on the next line, only when using Method 2 above */
    for (auto child = children_.rbegin(); child != children_.rend(); ++child) {}
}

更新

  • 程序是单线程的。
  • 进入for循环时抛出异常,发生零迭代。
  • 使用MSVC进行编译。
  • 使用空for循环的相同异常。
  • 重写示例以说明std::function问题。

1 个答案:

答案 0 :(得分:2)

很明显

  • auto定义了子的迭代器类型,由编译器静态确定(它不能在调用之间改变)。
  • child的类型与[{1}}和rbegin()
  • 兼容
  • rend()的类型是直接调用时与child兼容的关系运算符,但在通过rbegin()包装器调用时不是
  • 由于bind()的类型无法更改,因此child的类型必须具有,在第二种情况下。

我看到了以下可能性。

  1. 向量是一个成员,因此迭代器类型将是指向成员的指针,指向成员的指针对如何使用它有一些限制。
  2. 第一种情况下rend()的值可能与绑定中捕获的值不同(例如,基类与派生类)
  3. this的值可以通过包装器传递,这会改变其类型行为。
  4. 总的来说,这很可能是一个MSVC错误。提供的代码不编译,我不愿意尝试修改,可能无法重现该错误。如果你可以发布一个编译的repro案例,我很乐意进一步调查并更新答案。