- •Ооп: Лекция 7. Стандартная библиотека шаблонов ч.1
- •Адаптеры stl-контейнеров
- •Категории итераторов
- •Итераторы stl-контейнеров
- •Реверс-итератор можно преобразовать в обычный итератор через метод base().
- •Примеры алгоритмов и итераторов
- •Недействительные итераторы
- •При удалении все элементы, стоящие правее, сдвигаются на одну ячейку влево. При этом, итератор, по-прежнему указывает на ту же самую позицию:
- •Затем, итератор инкрементируется, указывая уже на следующую позицию:
- •При работе с другими контейнерами также следует соблюдать осторожность, и задумываться о ситуациях, при которых могут появляться недействительные итераторы:
- •Алгоритмы стандартной библиотеки
- •Пример использования изученных элементов stl
- •Полные примеры из лекции
Категории итераторов
Различные языковые конструкции (например, интервальный цикл for), средства стандартной библиотеки С++, а также собственные алгоритмы программиста могут взаимодействовать и со стандартными контейнерами, и с пользовательскими структурами данных через итераторы.
Требования к операциями, поддерживаемым итераторами, могут различаться в зависимости от потребностей алгоритма, которых их использует. Очевидно, для простого перебора элементов с целью вывода на экран и для сортировки элементов потребуются различные наборы манипуляций. По таким наборам итераторы стандартной библиотеки разделяются на 5 категорий:
входные итераторы (input iterators);
выходные итераторы (output iterators);
однонаправленные итераторы (forward iterators);
двунаправленные итераторы (bidirectional iterators);
итераторы произвольного доступа (random access iterators).
Простейшим вариантом является входной итератор (input iterator). Такой итератор предполагает предоставление следующих операций:
возможность копирующего присвоения (=);
возможность сравнения двух итераторов на равенство (==) и неравенство (!=);
возможность перемещения итератора вперед на одну позицию (оператор ++ в префиксной и постфиксной формах);
возможность чтения значения, на которое указывает итератор (оператор разыменования с целью чтения).
Выходной итератор (output iterator) похож на входной, с той разницей, что предоставляет операцию разыменования только с целью записи, а не чтения.
Однонаправленный итератор (forward iterator) объединяет возможности входного и выходного итераторов, т.е. операция разыменования доступна и для чтения, и для записи значений. Такой итератор в состоянии предоставить практически любая структура данных. Именно такой тип итератора применялся в примере о связных списках в лекции о перегрузке операторов.
Двунаправленный итератор (bi-directional iterator) дополнительно позволяет перемещать себя в обратном направлении (оператор --), т.е., просматривать стоящую за ним структуру данных и вперед, и назад. Такой тип итератора накладывает бОльшие ограничения на набор структур данных, которые могут его предоставить. В частности, движение в обратном направлении невозможно эффективно реализовать для односвязных списков, но легко для двусвязных.
Наконец, итератор произвольного доступа (random access iterator) является самым насыщенным и требовательным видом итератора. К списку требований необходимо добавить:
операторы сложения и вычитания с целым числом - перемещение на N позиций (+, +=, -, -=);
оператор вычитания двух итераторов (определение расстояния);
остальные способы сравнения (<, <=, >, >=);
оператор индексной выборки [].
Такой итератор может быть нереальным предоставить для многих структур данных, в частности, для связных списков. Теоретически такая реализация возможна, однако на практике любая операция будет характеризоваться линейной сложностью. Алгоритмы, ожидающие итератор данного типа, часто построены на предположении, что любая операция с итератором не зависит от объема данных, т.е. обладает константной вычислительной сложностью. Требование передачи итератора с произвольным доступом - это предположение, что структура данных является массивом или вектором, или другой структурой, похожей на них.
Графически иерархию категорий итераторов можно представить следующим образом:
В частности, рассмотренные контейнеры стандартной библиотеки предоставляют такие итераторы:
Контейнер |
Тип итераторов |
std::vector |
random access |
std::list |
bidirectional |
std::forward_list |
forward |
std::deque |
random access |
std::array |
random access |
