Гарантируют ли итераторы STL достоверность после изменения коллекции? - PullRequest
29 голосов
/ 25 июля 2010

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

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

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

Ответы [ 3 ]

43 голосов
/ 25 июля 2010

Зависит от контейнера.например, если это 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)

8 голосов
/ 25 июля 2010

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

4 голосов
/ 25 июля 2010

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

...