我正在为我的程序编写一个小型 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
问题。
最佳答案
很明显
auto
为 child 定义一个迭代器类型,由编译器静态确定(它不能在调用之间改变)。child
的类型赋值与rbegin()
和rend()
兼容child
的类型在直接调用时是与rbegin()
兼容的关系运算符,但在通过bind()
包装器调用时则不兼容- 因为
child
的类型不能改变,在第二种情况下rend()
的类型必须有。
我看到了以下可能性。
- vector 是成员,因此迭代器类型将是指向成员的指针,而指向成员的指针对其使用方式有一些限制。
- 第一种情况下
this
的值可能与绑定(bind)中捕获的值不同(例如,基类与派生类) this
的值可以通过包装器传递,这会改变其类型行为。
总的来说,这很可能是 MSVC 错误。提供的代码无法编译,我不愿意尝试修改并且可能无法重现错误。如果您可以发布编译的重现案例,我很乐意进一步调查并更新答案。
关于c++ - 为什么我会收到错误 'vector iterators incompatible' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23930602/