【问题标题】:"Vector Iterators Incompatible" when calculating distance between two iterators计算两个迭代器之间的距离时出现“向量迭代器不兼容”
【发布时间】:2019-02-23 13:56:18
【问题描述】:

我遇到了一个我无法完全找到原因的问题。

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

当我这样写代码时,一切都很完美

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

但是,如果我尝试用它制作一个衬里

return insert(object) - begin();

我得到了前面提到的“向量迭代器不兼容”的断言。

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() 都在同一个向量上工作。所有必要的 typedef 也都已到位。

【问题讨论】:

    标签: c++ visual-c++ visual-studio-2013 stl


    【解决方案1】:

    vector::insert 使迭代器无效。在表达式中insert(object) - begin() begin() 可以在insert 之前或之后调用。如果它之前被调用过,它会被insert() 无效化。 Order of evaluation:

    几乎所有 C++ 运算符的操作数的求值顺序(包括函数调用表达式中函数参数的求值顺序和任何表达式中子表达式的求值顺序)未指定。编译器可以按任何顺序计算操作数,并且在再次计算同一表达式时可能会选择其他顺序。

    而当你这样做时:

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

    begin()insert() 之后调用,因此返回一个有效的迭代器。

    【讨论】:

    • 是的,我知道 insert() 使迭代器无效(好吧,无论如何,在插入对象之后的迭代器),但是如何/为什么在 insert() 之前调用 begin()?
    • @azrael 为您更新了答案。
    • "@Maxim Egorushkin" 谢谢。必须正确检查您提供的链接。
    猜你喜欢
    • 2021-12-20
    • 2012-01-15
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    相关资源
    最近更新 更多