10.4.1. Итераторы вставки
Адаптер вставки (inserter), или адаптер inserter, — это адаптер итератора (см. раздел 9.6), получающий контейнер и возвращающий итератор, позволяющий вставлять элементы в указанный контейнер. Присвоение значения при помощи итератора вставки приводит к вызову контейнерной функции, добавляющей элемент в определенную позицию заданного контейнера. Операторы, поддерживающие эти итераторы, приведены в табл. 10.2.
Таблица 10.2. Операторы итератора вставки
it = t Вставляет значение t в позицию, обозначенную итератором it. В зависимости от вида итератора вставки и с учетом того, что он связан с контейнером с, вызывает функции c.push_back(t), c.push_front(t) и c.insert(t, p), где p — позиция итератора, заданная адаптеру вставки *it, ++it, it++ Эти операторы существуют, но ничего не делают с итератором it. Каждый оператор возвращает итератор itСуществуют три вида адаптеров вставки, которые отличаются позицией добавляемых элементов.
• Адаптер back_inserter (см. раздел 10.2.2) создает итератор, использующий функцию push_back().
• Адаптер front_inserter создает итератор, использующий функцию push_front().
• Адаптер inserter создает итератор, использующий функцию insert(). Кроме имени контейнера, адаптеру inserter передают второй аргумент: итератор, указывающий позицию, перед которой должна начаться вставка.
Адаптер front_inserter можно использовать, только если у контейнера есть функция push_front(). Аналогично адаптер back_inserter можно использовать, только если у контейнера есть функция push_back().
Важно понимать, что при вызове адаптера inserter(с, iter) возвращается итератор, который при использовании вставляет элементы перед элементом, первоначально обозначенным итератором iter. Таким образом, если it — итератор, созданный адаптером inserter, то присвоение *it = val; ведет себя, как следующий код:
it = c.insert(it, val); // it указывает на недавно добавленный элемент
++it; // инкремент it, чтобы он указывал на тот же элемент,
// что и прежде
Итератор, созданный адаптером front_inserter, ведет себя прямо противоположно итератору, созданному адаптером inserter. При использовании адаптера front_inserter элементы всегда вставляются перед текущим первым элементом контейнера. Даже если переданная адаптеру inserter позиция первоначально обозначает первый элемент, то, как только будет вставлен элемент перед этим элементом, он больше не будет элементом в начале контейнера:
list<int> lst = {1,2,3,4};
list<int> lst2, lst3; // пустой список
// после завершения копирования, lst2 содержит 4 3 2 1
copy(lst.cbegin(), lst.cend(), front_inserter(lst2));
// после завершения копирования, lst3 содержит 1 2 3 4
copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin()));
Когда происходит вызов front_inserter(c), возвращается итератор вставки, который последовательно вызывает функцию push_front(). По мере вставки каждого элемента он становится новым первым элементом контейнера с. Следовательно, адаптер front_inserter возвращает итератор, который полностью изменяет порядок последовательности, в которую осуществляется вставка; адаптеры inserter и back_inserter так не поступают.
Упражнения раздела 10.4.1
Упражнение 10.26. Объясните различия между тремя итераторами вставки.
Упражнение 10.27. В дополнение к функции unique() (см. раздел 10.2.3) библиотека определяет функцию unique_copy(), получающую третий итератор, обозначающий назначение копирования уникальных элементов. Напишите программу, которая использует функцию unique_copy() для копирования уникальных элементов вектора в первоначально пустой список.
Упражнение 10.28. Скопируйте вектор, содержащий значения от 1 до 9, в три других контейнера. Используйте адаптеры inserter, back_inserter и front_inserter соответственно для добавления элементов в эти контейнеры. Предскажите вид результирующей последовательности в зависимости от вида адаптера вставки и проверьте свои предсказания на написанной программе.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОК