Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_ Лекция №07 - Стандартная библиотека шаблонов ч.1 .docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
296.29 Кб
Скачать

Категории итераторов

Различные языковые конструкции (например, интервальный цикл 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