Итератор не совпадает с самим контейнером.Итератор ссылается на один элемент в контейнере, а также предоставляет способы для доступа к другим элементам.
Рассмотрите возможность создания собственного контейнера без итераторов.Он может иметь функцию size
для получения количества элементов, которые он содержит, и может перегрузить оператор []
, чтобы позволить вам получить или установить элемент по его позиции.
Но "произвольный доступ" изэтот вид нелегко реализовать на некоторых видах контейнеров.Если вы получите миллионный элемент: c[1000000]
, и контейнер внутренне использует связанный список, ему придется просканировать миллион элементов, чтобы найти нужный.
Вместо этого вы можете разрешить коллекции собиратьзапомнить «текущий» предмет.Он может иметь такие функции, как start
и more
и next
, чтобы позволить вам перебирать содержимое:
c.start();
while (c.more())
{
item_t item = c.next();
// use the item somehow
}
Но это помещает «состояние итерации» внутри контейнера.Это серьезное ограничение.Что если вы хотите сравнить каждый элемент в контейнере с любым другим элементом?Это требует двух вложенных циклов, оба перебирают все элементы.Если контейнер сам хранит позицию итерации, у вас нет возможности вложить две такие итерации - внутренний цикл разрушит работу внешнего цикла.
Таким образом, итераторы являются независимой копией состояния итерации.Вы можете начать итерацию:
container_t::iterator i = c.begin();
Этот итератор, i
, является отдельным объектом, который представляет позицию в контейнере.Вы можете выбрать все, что хранится в этой позиции:
item_t item = *i;
Вы можете перейти к следующему элементу:
i++;
С помощью некоторых итераторов вы можете пропустить несколько элементов вперед:
i += 1000;
Или получить элемент в некоторой позиции относительно позиции, определенной итератором:
item_t item = i[1000];
А с некоторыми итераторами вы можете двигаться назад.
И вы можете обнаружить, есливы вышли за пределы содержимого контейнера, сравнив итератор с end
:
while (i != c.end())
Вы можете думать о end
как о возвращении итератора, который представляет позицию, которая находится на одну позицию после последней позициив контейнере.
Важным моментом, который следует учитывать при использовании итераторов (и в целом в C ++), является то, что они могут стать недействительными.Это обычно происходит, например, если вы опорожняете контейнер: любые итераторы, указывающие на позиции в этом контейнере, теперь становятся недействительными.В этом состоянии большинство операций над ними не определены - все может произойти!