2010-07-25 3 views
27

Предположим, у меня есть какая-то коллекция, и я получил итератор для его начала. Теперь предположим, что я модифицировал коллекцию. Могу ли я использовать итератор безопасно, независимо от типа коллекции или итератора?Итераторы STL гарантируют действительность после изменения коллекции?

Чтобы избежать путаницы, здесь порядок операций я говорю о:

  1. Получить итератор коллекции.
  2. Изменить коллекцию (очевидно не элемент в ней, а сама коллекция).
  3. Используйте итератор, полученный на шаге 1. Является ли он действительным в соответствии со стандартом STL ?!
+0

Спасибо всем за быстрые ответы. – user88637

ответ

40

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

  • итераторы вектора, являются недействительными, если его память перераспределяется. Кроме того, вставка или удаление элемента в середине вектора аннулирует все итераторы, указывающие на элементы, следующие за точкой вставки или удаления. Из этого следует, что вы можете помешать итераторам вектора быть недействительными, если вы используете reserve() для предопределения столько памяти, сколько будет использоваться вектором, и если все вставки и удаления находятся на конце вектора. [1]

  • Семантика недействительности итератора для deque заключается в следующем. Insert (включая push_front и push_back) аннулирует все итераторы, ссылающиеся на deque. Erase в середине deque аннулирует все итераторы, ссылающиеся на deque. Erase в начале или конце deque (включая pop_front и pop_back) аннулирует итератор, только если он указывает на стертый элемент. [2]

  • List s имеют важное свойство, что вставка и сплайсинг не аннулирует итераторы в список элементов, и даже удаление аннулирует только итераторы, которые указывают на элементы, которые будут удалены. [3]

  • Map имеет важное свойство, вставляя новый элемент в map не аннулирует итераторы, которые указывают на существующие элементы. Стирание элемента с карты также не отменяет никаких итераторов, за исключением, конечно, для итераторов, которые фактически указывают на стираемый элемент. [4] (то же самое для set, multiset и multimap)

+1

Однако, 'vector :: insert' (один элемент) и' vector :: erase', возвращает новый, действительный итератор. –

+1

Кенни: Это то, что вы говорите правду в соответствии со стандартом или истинным, потому что это так, как обычно применяется stl? Можете ли вы изменить свой ответ, чтобы он также объяснил это? Благодарю. – user88637

+8

@ yossi1981: Это определено стандартом. Условия, при которых итераторы недействительны, очень четко определены в стандарте. –

4

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

+1

Строго говоря, это неверно (список примеров не соответствует этим правилам). –

+1

Вопрос задавался «независимо от типа коллекции (контейнера)». – m1tk4

+0

Независимо от вопроса, заявление, сделанное в вашем ответе, вводит в заблуждение, потому что оно истинно в некоторых случаях и ложно в (многих) других. – user487158

8

Это зависит от коллекции под вопросом. Например, изменение std::vector (например, добавление элемента) может привести к недействительности всех итераторов в этом векторе.Напротив, с std::list, итераторы остаются в силе, когда вы добавляете в список еще один элемент. В некоторых случаях правила еще сложнее (например, если память работает с std::deque, добавление к началу или концу оставляет существующие итераторы действительными, но добавление где-либо еще может привести к их недействительности - но моя память достаточно бедна, проверьте до этого в зависимости от этого).

+2

Что делать, если вы удалите элемент списка? Что, если это элемент, на который указывает итератор? – m1tk4

+0

Стирание элемента, на которое ссылается итератор, делает недействительным этот итератор. Стирание любых других элементов (ов) не выполняется. –

+0

Другими словами, если вы изменяете список, есть обстоятельства, когда он аннулирует итератор (указывая на стертый элемент), поэтому срок действия итератора не гарантируется - правильно? – m1tk4

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