На этом шаге мы рассмотрим прямые итераторы.
Прямые итераторы представляют собой комбинацию итераторов ввода и вывода. Они обладают всеми свойствами итераторов ввода и
большинством свойств итераторов вывода. Операции прямых итераторов перечислены в таблице 1.
Таблица 1. Операции прямых итераторов
Выражение | Описание |
---|---|
*iter | Обращение к элементу |
iter->member | Обращение к переменной или функции элемента |
++iter | Смещение вперед (возвращает новую позицию) |
iter++ | Смещение вперед (возвращает старую позицию) |
iter1 == iter2 | Проверка двух итераторов на равенство |
iter1 != iter2 | Проверка двух итераторов на неравенство |
TYPE() | Копирование итератора (конструктор по умолчанию) |
TYPE(iter) | Копирование итератора (копирующий конструктор) |
iter1 = iter2 | Присваивание итератора |
В отличие от итераторов ввода и вывода прямые итераторы могут ссылаться на один и тот же элемент коллекции и обрабатывать его по
несколько раз.
Возможна, вас интересует, почему прямой итератор не обладает всеми свойствами итератора вывода. Существует одно важное
ограничение, из-за которого код, действительный для итераторов вывода, оказывается недействительным для прямых итераторов.
- Итераторы вывода позволяют записывать данные без проверки конца последовательности. Более того, вы даже не
можете сравнить итератор вывода с конечным итератором, потому что итераторы вывода не поддерживают операцию сравнения.
Следовательно, для итератора вывода pos следующий цикл правилен, а для прямого итератора - нет:// ОК для итераторов вывода // ОШИБКА для прямых итераторов while (true) { *pos = foo(); ++pos; }
- При работе с прямыми итераторами перед разыменованием (обращением к данным) необходимо заранее убедиться в том,
что это возможно. Приведенный выше цикл неправилен для прямых итераторов, поскольку он приводит к попытке обращения по
итератору end() в конце коллекции с непредсказуемыми последствиями. Для прямых итераторов цикл необходимо изменить
следующим образом:// ОК для прямых итераторов // ОШИБКА для итераторов вывода while (pos != coll.end()) { *pos = foo(); ++pos: }
Для итераторов вывода цикл не компилируется, потому что для них не определен оператор !=.
На следующем шаге мы рассмотрим двунаправленные итераторы.