2011-12-06 4 views
2

Я потерян: Итератор вектора std :: string отлично работает, если нет вызова функции (Z_UB-> set()) перед ним ++. Вот код:C++ Iterator случайно недействителен

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 
std::cout << "begin of vector: " << *it << std::endl; 
Z_UB->set("s1", "scn2", 350); 
it++; 
std::cout << "second of vector: " << *it << std::endl; 

создает следующий вывод

begin of vector: scn1 

Однако, если я перееду вызов функции следующим образом:

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 
std::cout << "begin of vector: " << *it << std::endl; 
it++; 
std::cout << "second of vector: " << *it << std::endl; 
Z_UB->set("s1", "scn2", 350); 

Результат следующий, что ожидаемый поведение:

begin of vector: scn1 
second of vector: scn2 

Внутри функции Z_UB-> набор() не осталось ничего, кроме самого вызова:

void Parameter::set(std::string _i, std::string _j, float value) { 
//int i = indexSets[0]->backIndex(_i); 
//int j = indexSets[1]->backIndex(_j); 

//data2D[0][0] = value; 
} 

Так что, если я вызываю функцию набора Z_UB->() после того, как я создал итератора, доступ к ней приведет к краху программы , Есть ли что-то жизненно важное, что я пропустил об Итераторах?

+2

Здесь не достаточно информации для диагностики вашей конкретной проблемы. Итераторы не становятся недействительными «случайным образом», поэтому проблема заключается в вашем коде, но неясно, из этого сообщения _where_ в вашем коде проблема. Действительно ли 'Z_UB' типа' Parameter'? Существуют ли какие-либо другие типы, которые могут быть, все, что изменяет базовый «вектор»? Итераторы 'vector' недействительны при изменении размера внутреннего хранилища' vector'. – Chad

+1

Получает ли getVector() ссылку на вектор или копию? –

+0

Он возвращает копию вектора (в терминах я не использовал & нигде) – buhmann

ответ

1

.getVector() возвращается копия вектора. Сравнение итератора с конечной точкой итератора совершенно другого объекта не имеет смысла. Возвращение справки решает проблему.

@Xeo также отметил, гораздо лучшее объяснение: При создании итератора из копии, как это:

std::vector<std::string>::iterator it = g_SPP.scenarios->getVector().begin(); 

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

+1

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

1

a std::vector<T>::iterator будет признан недействительным, если вы добавите или удалите элементы во время итерации по нему, если вектору необходимо изменить размер внутри себя, когда элемент будет добавлен.

+0

из примера кода это не то, что здесь происходит ... – Benoit

2

Если g_SPP является глобальным переменной, то итераторы над ним будут аннулированы любой мутирующей операцией.


Update - это от спецификации 1998 ISO/ANSI:

Следующая аннулирует все ссылки, итераторы и указатели, относящиеся к элементам последовательности, если требуется назначение. Выделение требуется, если текущий capacity() меньше размера целевого вектора.

  • void reserve(size_type n)
  • iterator insert(iterator position, const T& x),
  • void insert(iterator position, size_type n, const T& x),
  • void insert(iterator position, InputIterator first, InputIterator last) и

Стирание аннулирует все ссылки, итераторы и указатели, относящиеся к элементам после позиции начального стертого элемента.

  • iterator erase(iterator position)
  • iterator erase(iterator first, iterator second)

Изменение размера вектора эквивалентно вызову либо insert или erase. Согласно 23.2.4.2/6: resize(sz, c=value_type()) имеет тот же эффект, как:

if (sz > size()) 
    insert(end(), sz - size(), c); 
else if (sz < size()) 
    erase(begin() + sz, end()); 
else 
    ; 
+0

интересно, не могли бы вы добавить ссылку, пожалуйста, пожалуйста? – Benoit

+0

Мутируя, вы имеете в виду добавление и удаление элементов только? –

2

Несколько возможностей:

  • Либо у вас нет хорошего воспроизводимых пример: может быть, в вашем первом запуске вы имели только один элемент в вашем векторе (как он заполнен?) и вызвал неопределенное поведение, потому что вы не проверили it против g_SPP.scenarios->getVector().end()
  • Или Z_UB->set не делает то, что вы думаете. Это полиморфный класс? Есть set виртуальный? Перегружен ли оператор ->?
  • Является ли ваше приложение многопоточным, а другой поток мутирует ваш контейнер?
+0

функция -> set перегружена, но я добавил некоторые отладочные данные для всех других версий. Вызывается только тот, который я ожидал запустить. – buhmann

 Смежные вопросы

  • Нет связанных вопросов^_^