«Несовместимые итераторы вектора» при расчете расстояния между двумя итераторами - PullRequest
0 голосов
/ 19 сентября 2018

У меня проблема, которую я не могу найти причину.

В определенный момент в моем коде я возвращаю расстояние между двумя итераторами std :: vector, один из которых является результатомоперация вставки в вектор, а другая указывает на начало вектора.Идея состоит в том, чтобы вернуть индекс вновь вставленного объекта.

Все отлично работает, когда я формулирую код следующим образом:

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

Однако, если я пытаюсь сделать один вкладыш изit

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 () работают с одним и тем же вектором.Все необходимые typedefs также на месте.

1 Ответ

0 голосов
/ 19 сентября 2018

vector::insert делает недействительными итераторы.В выражении insert(object) - begin() begin() может вызываться до или после insert.Если он вызывается раньше, он становится недействительным insert(). Порядок вычисления :

Порядок вычисления операндов почти всех операторов C ++ (включая порядок вычисления аргументов функции в выражении вызова функции и порядок вычисленияподвыражений в любом выражении) не определено.Компилятор может вычислять операнды в любом порядке и может выбирать другой порядок при повторном вычислении того же выражения.

Тогда как при выполнении:

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

begin() вызываетсяпосле insert() и, следовательно, возвращает действительный итератор.

...