- •Итераторы
- •Основные понятия
- •Классификация итераторов
- •Свойства итераторов различных типов
- •Последовательные итераторы
- •Двунаправленные итераторы2
- •Итераторы произвольного доступа3
- •Итераторы ввода
- •Итераторы вывода
- •Использование итераторов
- •Вставка одного или нескольких элементов в позицию, указываемую итератором
- •Адаптеры итераторов и итераторы потоков ввода-вывода
- •Итераторы потоков ввода-вывода
- •Итераторы вставки (insert iterators).
- •Функции advance и distance
- •Теги и свойства итераторов5
- •Как написать свой итератор
Классификация итераторов
В STL Существует 5 категорий итераторов, в зависимости от определенных для них операций и правил использования:
Итераторы последовательного доступа
Двунаправленные итераторы (bidirectional)
Итераторы произвольного доступа (random access)
Итераторы ввода (input)
Итераторы вывода (output)
Итераторы также могут быть константными (constant, read-only) и изменяемыми (read/write или write-only): константный итератор допускает лишь чтение, изменяемый допускает запись. Не следует неверно понимать слово «константный» как невозможность изменить сам итератор – оно означает лишь невозможность изменить значение элемента, на который указывает итератор. Кроме того в данном случае константный итератор не является обычным итератором объявленным с модификатором const, это другой тип итератора, так стандартные контейнеры (например vector) поддерживают два имени типа iterator для неконстантных итераторов и const_iterator для константных.
Итератор последовательного доступа позволяет осуществлять перебор элементов коллекции лишь последовательно в одном направлении. Таков, к примеру, итератор потока данных от какого-нибудь устройства.
Двунаправленные итераторы позволяют просматривать коллекцию в двух направлениях, т.е. для каждого элемента перейти к следующему или предыдущему – например, итератор двухсвязного списка.
Итератор произвольного доступа позволяет обратиться к элементу непосредственно по его номеру. Типичный пример – обычный массив или vector.
Итератор ввода представляет собой частный случай последовательного константного итератора. Его важным отличием от вышеупомянутых типов является то, что
Если i достижим из j и i!=j, то действительным в общем случае является только i, но не j
Два итератора ввода в общем случае равны (и – более того – одновременно действительны) тогда и только тогда, когда это копии одного и того же итератора
Алгоритмы, использующие итератор ввода, не должны проходить через одно значение итератора дважды, т.е. должны быть однопроходными.
Эти свойства становятся очевидными, если вспомнить, что итератор ввода может быть, к примеру, итератором потока данных: увеличение итератора означает выбор следующего байта из потока и при этом 1) теряется предыдущий байт и 2)Рассмотрим выражение ++i==++j. ++i и ++j будут в любом случае выполнены последовательно и если первым будет увеличен итератор i, то после этого j будет уже недействительным и для него результат операции инкремента будет неопределен.
Итератор вывода – также частный случай последовательного итератора. Помимо свойств, аналогичных вышеописанным свойствам итератора ввода он обладает еще одним: прежде чем увеличивать итератор вывода, необходимо что-нибудь записать в элемент, указываемый им, т.е. последовательность действий j++; j++ недопустима.
Заметим, что эти итераторы укладываются в следующую иерархию:
То есть последовательный итератор удовлетворяет требованиям итератора ввода и вывода, двунаправленный итератор – требованиям последовательного, произвольного доступа – требованиям двунаправленного. Более четкую формализацию свойств различных категорий итераторов см. в части «Свойства различных типов итераторов».
Константные итераторы предоставляют пользователю лишь право чтения указываемых элементов последовательности. Изменяемые либо предоставляют только право записи, либо право и чтения, и записи.
Всякий итератор ввода, к примеру, является константным; итератор массива обычно предоставляет право и чтения, и записи; всякий итератор вывода предоставляет только право записи.
