Векторные итераторы несовместимы - PullRequest
37 голосов
/ 07 декабря 2011

У меня есть класс с элементом данных std :: vector, например,

class foo{
public:

const std::vector<int> getVec(){return myVec;} //other stuff omitted

private:
std::vector<int> myVec;

};

Теперь в некоторой части моего основного кода я пытаюсь перебрать вектор так:

std::vector<int>::const_iterator i = myFoo.getVec().begin();
while( i != myFoo.getVec().end())
{
   //do stuff
   ++i;
}

В тот момент, когда я достигаю этого цикла, я получаю вышеупомянутую ошибку.

Ответы [ 10 ]

70 голосов
/ 07 декабря 2011

Причина, по которой вы получаете это, в том, что итераторы из двух (или более) разных копий myVec. Вы возвращаете копию вектора при каждом вызове myFoo.getVec(). Таким образом, итераторы несовместимы .

Некоторые решения:

Возвращает постоянную ссылку на std::vector<int>:

const std::vector<int> & getVec(){return myVec;} //other stuff omitted

Другое решение, вероятно, предпочтительнее, это получить локальную копию вектора и использовать ее для получения итераторов:

const std::vector<int> myCopy = myFoo.getVec();
std::vector<int>::const_iterator i = myCopy.begin();
while(i != myCopy.end())
{
  //do stuff
  ++i;
}

Также +1 для не using namespace std;

10 голосов
/ 07 декабря 2011

Вы возвращаете копию вектора. Поскольку вы возвращаете по значению - ваши вызовы begin () и end () предназначены для совершенно разных векторов Вам необходимо вернуть const & to.

const std::vector<int> &getVec(){return myVec;}

Я бы сделал это немного иначе. Я бы сделал класс немного похожим на стандартный контейнер

class Data
{
   public:
      typedef std::vector<int>::const_iterator const_iterator;

      const_iterator begin() const { return myVec.begin(); }
      const_iterator end() const { return myVec.end(); }
};

Data::const_iterator i=myFoo.begin();

while(i != myFoo.end())
{
//
}
4 голосов
/ 21 мая 2016

Другая причина утверждения отладки MSVC STL «несовместимые векторные итераторы» заключается в работе недействительного итератора.

Т.е. v.erase(i), а затем сравнение i != v.end() стирание аннулирует i, поэтому его нельзя использовать в сравнении.

2 голосов
/ 31 декабря 2013

Другая причина, по которой это утверждение может сработать, заключается в том, что вы должны выделить «foo» с помощью «malloc» вместо «new», эффективно пропуская конструктор (ы).

Маловероятно, что это случится с проектом, разработанным с нуля в C ++, но при преобразовании кода обычного C в C ++ (замена статического массива [] в некоторой структуре на stl-вектор) вы можете просто не понимать, чтодинамические экземпляры указанной структуры (и члены внутри) не будут вызывать свой конструктор - если только вы не измените 'malloc' на 'new'.

2 голосов
/ 27 июля 2013

ну, я не думаю, что векторная копия могла быть единственной причиной, которая кажется мне слишком очевидной.

в моем случае я просто обнаружил, что поврежденный стек, куча, непредвиденные изменения также могут привести к этому сбою, и он фактически скрывает основную причину. в моем случае я перешел на использование индексатора для итерации и поиска основной причины.

2 голосов
/ 07 декабря 2011

Проблема в том, что вы всегда возвращаете другую копию вектора.Используйте ссылку:

const std::vector<int>& getVec(){return myVec;} //other stuff omitted
1 голос
/ 07 декабря 2011

Изменить

const std::vector<int> getVec(){return myVec;}

на

const std::vector<int>& getVec(){return myVec;}
1 голос
/ 07 декабря 2011

Вы делаете постоянную копию вектора-члена, не обращаясь к вектору-члену.

Изменить это:

const std::vector<int> getVec(){return myVec;} //other stuff omitted

к этому:

const std::vector<int> & getVec(){return myVec;} //other stuff omitted

Чтобы пойти немного глубже, итератор, который вы получаете из этого утверждения:

std::vector<int>::const_iterator i = myFoo.getVec().begin();

является итератором для временной копии вашего вектора, которая исчезает после выполнения этого оператора, что делает итератор недействительным.

0 голосов
/ 16 августа 2016

Поскольку вы возвращаете по значению - ваши вызовы begin () и end () предназначены для совершенно разных векторов.Вам необходимо вернуть const & to

0 голосов
/ 07 декабря 2011

Ваша функция getVec () возвращает глубокую копию вектора-члена, поэтому два вызова getVec (), которые вы делаете для получения итераторов, передают итераторы в разные контейнеры.То есть вы не можете получить доступ к getVec (). End () из отдельного итератора getVec (). Begin () без вызова неопределенного поведения.

Это можно решить двумя способами:

1) Пусть getVec вернет константную ссылку (то есть const std :: vector &) (предпочтительно) или ...

2) Замените два вызова getVec () одним и сохраните результат в std:: векторная переменная.Затем используйте эту переменную для обоих вызовов begin () и end ().Например:

std::vector<int> v = myFoo.getVec();
std::vector<int>::const_iterator b = v.begin();
std::vector<int>::const_iterator e = v.end();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...