计算两个迭代器之间的距离时出现“向量迭代器不兼容”的错误提示。

4

我遇到了一个问题,但是我无法找出其原因。

在我的代码中的某个特定点,我返回两个std::vector迭代器之间的距离,其中一个是插入操作在向量上的结果,另一个则指向向量的开头。我的想法是返回新插入对象的索引。

当我将代码表述为如下形式时,一切都完美运行:

const_iterator (or auto) it = insert(object);
return it - begin();

然而,如果我试图将其简洁地表达成一行
return insert(object) - begin();

我收到了"Vector Iterators Incompatible"的断言信息。
begin() 的实现如下:
MyClass::iterator MyClass::begin()
{
  return m_container.begin();
}

insert()的实现方式如下:

MyClass::iterator MyClass::insert(MyObject *object)
{
  if (object)
  {
    const_iterator it = std::lower_bound(begin(), end(), object, DereferencedLess<MyObject >());

    if (it == end() || *(*it) != *object)
      return m_container.insert(it, object);
  }

  return end();
}

课程简介:

MyClass {
  ...
  iterator  begin();
  const_iterator begin() const;
  iterator  insert(MyObject*);

  ...
  protected:
  std::vector<MyObject*> m_container;
}

为了完备起见

template<typename T>
struct DereferencedLess
{ inline bool operator()(const T *p1, const T *p2) const { return *p1 < *p2; } };

我非常希望能够理解为什么会出现这个断言错误。据我所见,迭代器类型相同,insert()和begin()方法也在同一个vector上工作。所有必要的typedefs也已经正确声明。

1个回答

7

vector::insert会使迭代器失效。在表达式insert(object) - begin()中,begin()可以在insert之前或之后被调用。如果在之前调用,则它将被insert()所使无效。关于“求值顺序”的更多信息,请参见求值顺序

几乎所有C++运算符(包括函数调用表达式中的函数参数的求值顺序和任何表达式中子表达式的求值顺序)的操作数求值顺序都是未指定的。编译器可以以任何顺序评估操作数,并且当再次评估相同表达式时可能选择另一种顺序。

而当您执行以下操作时:

const_iterator (or auto) it = insert(object);
return it - begin();

begin()insert() 后被调用,因此返回有效迭代器。


是的,我理解insert()使迭代器失效(至少是插入对象之后的迭代器),但是在调用insert()之前怎样/为什么可以调用begin()呢? - marcbf
@azrael,我已经为您更新了答案。 - Maxim Egorushkin
@Maxim Egorushkin 感谢您的帮助。我需要仔细查看您提供的链接。 - marcbf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接