Скачиваний:
62
Добавлен:
05.07.2021
Размер:
94.13 Кб
Скачать

Входные итераторы

Входной итератор предназначен для считывания значений из контейнера. Разыменование входного итератора должно приводить к чтению элементов из контейнера, но не обязательно должно позволять модифицировать это значение. Алгоритмы, требующие входных итераторов, не изменяют содержимое контейнера. Входной итератор должен обеспечивать доступ ко всех значениям контейнера. Нет никакой гарантии, что второй проход по элементам контейнера с помощью входного итератора будет выполнен в той же последовательности, потому что это определяет контейнер. Не существует гарантий, что после увеличения значения входного итератора на 1 его предыдущее значение останется доступным для разыменования.

Входной итератор должен быть однонаправленным и не зависеть от значений итератора из предшествующего прохода или предшествующих значений этого же итератора. Его можно инкрементировать, но нельзя декрементировать. Таким образом вывод программы является вводом для контейнера.

Выходной итератор аналогичен входному за исключением того, что его разыменование дает возможность изменения значения, но не всегда его чтения.

Выходной итератор может применяться для алгоритмов однократного прохода с доступом только для записи. А входной только для чтения

Однонаправленные итераторы

Предназначен для перемещения по элементам контейнера только вперед, но при каждом проходе он обязательно перебирает элементы контейнера в той же последовательности. После инкрементирования однонаправленного итератора предыдущее значение по прежнему можно разыменовать, что даст то же самое значение для многопроходных алгоритмов. Позволяет как чтение, так и модификацию данных.

Двунаправленные итераторы

Обладают всеми свойствами однонаправленных, но еще поддерживают декремент, как префиксный, так и постфиксный.

Произвольного доступа

Сортировка, поиск требуют возможности перехода на произвольный элемент контейнера, что требует соответствующий итератор. Итератор произвольного доступа обладает всем от двунаправленного, а так же операцией произвольного перемещения, операцией отношения для возможности упорядочивания элементов.

Алгоритмы, записанные в терминах определенного вида итераторов не могут получать любой другой, но контейнер, поддерживающий произвольный доступ, может использовать нижестоящий.

12 мая 2021

Лекция 14 Двунаправленные итераторы

Идея использования разных видов итераторов состоит в том, чтобы написать алгоритм, использующий итератор с минимально необходимыми требованиями, что позволит применять его с максимальным множеством различных контейнеров. Так, например, функция find за счет использования в ней входного итератора может применяться с любым контейнером, который содержит читаемые значения. А сорт может выполняться только с контейнерами, поддерживающими произвольный доступ.

Итераторы являются обобщением указателей и отвечают всем их требованиям. Итераторы образуют интерфейс для алгоритмов stl. Алгоритм copy может копировать из одного контейнера в другой, поскольку в качестве итератора можно применять указатели на массив. Первые 2 аргумента – диапазон, который необходимо скопировать, а третий – куда копировать. Первые 2 входные и более совершенные итераторы, а послейдний – выходной. Функция copy всегда переписывает данные в контейнере назначения и контейнер назначения должен быть достаточно велик, чтобы поместить все копируемые элементы.

Класс ostream_iterator можно создать, подключив заголовочный файл iterator.

ostream_iterator<int, char> out_iter(cout, “ “).

int – тип данных, отправляемые в выходной поток

char – тип, используемый выходным потоком (cout)

Первый аргумент конструктора cout определяет используемый выходной поток, вместо него можно быть использовать fstream.

Для обычного указателя запись

*out_iter++ = 15;

означала бы присваивание значения указателю out_iter с последующим инкрементированием, но для объекта типа out stream iterator говорит об отправке значения “15” в поток, добавления разделителя и перемещения на следующую позицию вывода.

Istream_iterator требует типа данных, который будет прочитан и второй – символьный тип, используемый входным потоком.

Использование аргумента конструктора cin означает считывание данных с клавиатуры. Отсутствие аргументов у этого итератора означает ошибку ввода, как способ завершения считывания данных.

Итераторы специального назначения:

  • reverse_iterator;

  • back_insert_iterator;

  • front_insert_iterator;

  • insert_iterator;

Reverse_iterator представляет собой класс инкрементирование которого вызывает декремент. Класс vector имеет метод rbegin() возвращающий обратный итератор, который указывает на элемент, находящийся за последним значимым. Метод rend(), который возвращает итератор на начало. Методы rbegin() и end() возвращают одно и то же значение за последним элементом, но разного типа:  rbegin - reverse_iterator, end - iterator.

Методы rend() и begin() возвращают одно и то же значение (итератор, указывающий на первый элемент), но разного типа : reverse_iterator  и iterator соответственно.

Обратные указатели обязательно сначала нужно декрементировать, а затем разыменовывать для предотвращения разыменования элемента, стоящего за последним значимым.

Когда есть возможность выбора между явным объявлением итератора и использованием функции STL , то следует отдавать предпочтение второму подходу. Итераторы back_insert_iterator, front_insert_iterator  часто называются просто итераторами вставки. Многие алгоритмы STL передают свои результаты по адресу, указанным выходным итератором, при этом некоторые функции предпринимают попытку изменения размера контейнера назначения, некоторые – нет. Эта особенность может быть решена использованием трех операторов вставки, преобразуя процесс копирования в процесс вставки. Вставка всегда добавляет новые элементы не перезаписывая существующие, при этом используется автоматическое выделение памяти для обеспечения необходимого размера контейнера.

Итератор back_insert_iterator вставляет элементы в конец контейнера, front_insert_iterator в начало, insert_iterator перед позицией, указанной в аргументе конструктора. Все эти три итератора соответствуют концепции выходного итератора.

Ограничения свойственные эти трем итератором:

  • back_insert_iterator может применяться только к контейнерам, которые допускают вставку в конец быстро, ? термин быстрый относится к алгоритмам с постоянным временем, класс вектор позволяет это делать.

  • front_insert_iterator может использоваться только с контейнерными типами, допускающие вставку в начало за постоянное время.  Класс вектор не позволяет это делать, а класс queue позволяет.

  • Insert_iterator можно применять для вставки данных в начало вектор, но использование front_insert_iterator будет выполняться быстрее с теми типами контейнеров, которые поддерживают его применение. Insert_iterator позволяет преобразовать копирующий алгоритм в алгоритм вставки.

При объявлении итератора обязательно указывать тип контейнера в связи с тем, что итератор будет применять соответствующий метод контейнера. Например, код конструктора back_insert_iterator будет исходить из предположения о том, что существует метод в контейнере (push_back) для переданного ему типа.

Объявление итератора insert_iterator содержит дополнительный аргумент для указания позиции вставки.

Объявление итератора insert_iterator содержит дополнительный аргумент для указания позиции ставки.