Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
STL_3.doc
Скачиваний:
7
Добавлен:
01.05.2025
Размер:
131.58 Кб
Скачать

4.7. Итераторы вставки

Итератор вставки переводит обобщенный алгоритм в "режим вставки", а не в "режим перезаписи". Это означает, что присваивание *i = ... приводит не к перезаписи объекта в позиции i, а к вставке его в эту позицию с применением функции-члена контейнера для вставки. Итераторы вставки особенно полезны при пересылке последовательности данных из входного потока или контейнера в другой контейнер, когда длина последовательности заранее неизвестна. STL предоставляет три типа итераторов вставки, каждый из которых параметризован типом Container:

• back_insert_iterator<Container> — использует функцию-член push_back

класса Container;

• front_insert_iterator<Container> — использует функцию-член push_front

класса Container;

• insert_iterator<Container> — использует функцию-член insert класса

Container.

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

vector<int> vector1; // vectorl пуст

deque<int> deque1(200, 1); // В dequel хранится 200 единиц.

copy(deque1.begin(), deque1.end(),

vector1.begin()); // ОШИБКА!

В процессе копирования возникает ошибка времени выполнения в инструкции

*(vector1.begin()) = *(deque1.begin())

Однако при использовании в качестве третьего аргумента итератора вставки алгоритм сору работает корректно, поскольку функция push_back вектора vector1 выполняет при необходимости перераспределение памяти:

copy(deque1.begin(), deque1.end(),

back_insert_iterator< vector<int> >(vector1));

Здесь back_insert_iterator<vector<int> > (vector1) вызывает конструктор

шаблона класса

template <typename Container>

class back_insert_iterator;

инстанцированный с vector<int> в качестве типа Container. Чтобы было удобнее

использовать итератор вставки, STL определяет шаблон обобщенной функции back_inserter.

template <typename Container>

inline back_insert_iterator<Container> // Возвращаемый тип

back_inserter(Container& x) {

return back_insert_iterator<Container>(x);

}

Таким образом, вызов copy можно записать более кратко:

copy(deque1.begin(), deque1.end(), back_inserter(vector1));

Компилятор автоматически инстанцирует функцию back_inserter с параметром типа Container, равным vector<int>. Инстанцированный экземпляр функции back_inserter вернет нам back_insert_iterator<Container>.

Итератор back_insert_iterator, а значит, и функция back_inserter, могут

использоваться с контейнерами vector, list и deque, поскольку все они имеют функцию-член push_back. Этот итератор вставки принимает любой контейнер С1, имеющий функцию-член push_back, и создает итератор с определенными в нем операторами * и = таким образом, что код

*i = х;

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

C1.push_back(x);

Кроме того, итератор i, по сути, всегда указывает на конец связанного с ним контейнера, а операции ++I и i++ нe выполняют никаких действий.

Аналогично, front_insert_iterator и связанный с ним шаблон функции

front_inserter осуществляют вставку в начало контейнера. Они могут использоваться с контейнерами list и deque, поскольку эти контейнеры имеют функцию-член push_front:

int array1[100];

deque<int> deque1;

// Присваивание значений arrayl[0] , ..., arrayl[99]:

copy(&array1[0], &array1[100], front_inserter(deque1));

Элементы arrayl будут находиться в начале deque1 (в порядке, обратном порядку этих элементов в array1).

Контейнер vector функции-члена push_front не имеет, поскольку такая операция имела бы линейное время работы (то же относится и к функции pop_front, как вы увидите при рассмотрении адаптера очереди в разделе 9.2). Таким образом, front_inserter не может работать с контейнером vector.

Наиболее общим итератором вставки является insert_iterator, который имеет

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

В этом случае элементы array1 будут вставлены после первого элемента deque1 и будут находиться в том же порядке, что и в array1 (т.е. после каждой вставки к итератору будет применяться операция инкремента ++, так что он будет перемещаться в позицию за только что вставленным элементом).

Итератор insert_iterator и функция inserter используют функцию-член

контейнера insert (iterator, value). Поскольку такая функция имеется у всех типов

контейнеров STL, inserter может применяться к контейнеру любого типа (включая отсортированные ассоциативные контейнеры).

Другие примеры использования итераторов вставки вы встретите в следующем разделе и в главах 5, "Обобщенные алгоритмы", и 12, "Программа для поиска в словаре".

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]