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

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

В предыдущем разделе мы видели, что входные итераторы могут использоваться для чтения значений последовательности, но запись при помощи входных итераторов возможна не всегда. Выходные итераторы обладают противоположной функциональностью: они позволяют записывать значения в последовательность, но не гарантируют возможность их чтения. То есть, если first — выходной итератор, то мы можем написать *first = ..., но не гарантируется возможность применения *first в выражении для получения значения, на которое указывает итератор. Еще одно отличие от требований для входных итераторов состоит в отсутствии обязательной поддержки операторов == и ! = для выходных итераторов. Что касается префиксного и постфиксного операторов ++, то здесь выходные итераторы идентичны входным. Как и в случае входных итераторов, термин "выходные итераторы" сам по себе не представляет никакой тип. Он может быть применен к любому типу, который удовлетворяет соответствующим требованиям.

Рассмотрим, например, алгоритм STL copy, который выполняет копирование из одной последовательности в другую:

template <typename Inputlterator, typename Outputlterator>

Outputlterator copy(InputIterator first,

Inputlterator last,

Outputlterator result)

{

while (first != last)

{

*result = *first;

++first;

++result;

}

return result;

}

И опять, обычные указатели могут выступать в роли выходных итераторов для встроенных массивов C++:

int а[100] , Ь[100] ;

// ... Код для сохранения значений в а[0], . . ., а[99]

сору(&а[0], &а[100], &Ь[0]);

Здесь выполняется копирование значений а [0], ..., а [99] в b [0], ..., b [99].

STL предоставляет специальные выходные операторы, которые называются

итераторами ostream, и используются для записи значений в выходной поток. Например, в приведенном далее фрагменте исходного текста элементы списка выводятся в выходной поток cout:

list<int> list1;

// ... Код для вставки значений в list1

// Объявление объекта итератора ostream:

ostream_iterator<int> out(cout, "\n");

copy(list1.begin(), list1.end(), out);

Аргументами конструктора ostream_iterator являются объект выходного потока и

строка, которая записывается между значениями в выходном потоке; в нашем случае символ новой строки обеспечивает вывод каждого значения в отдельной строке. Итераторы ostream более детально будут рассмотрены в разделе 4.8.

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

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

Мы уже видели, что входные итераторы могут использоваться для чтения значений последовательности, а выходные — для их записи. Однонаправленный итератор (forward iterator) — это итератор, который объединяет в себе и входной, и выходной итераторы, тем самым обеспечивая возможность чтения и записи и обхода последовательности в одном направлении. Однонаправленные итераторы обладают также свойством, которое не требуется ни для входных, ни для выходных итераторов: возможностью сохранить однонаправленный итератор и использовать сохраненное значение для повторного прохода из того же положения. Это свойство позволяет однонаправленным итераторам использоваться в многопроходных алгоритмах, в отличие от однопроходных алгоритмов, таких как find и merge.

В качестве примера алгоритма, который выполняет и чтение, и запись последовательности, рассмотрим алгоритм STL replace, который заменяет все значения х в диапазоне [first; last) другим значением у:

template <typename Forwardlterator, typename T>

void replace(Forwardlterator first, Forwardlterator last,

const T& x, const T& y)

{

while (first != last)

{

if (*first == x)

*first = y;

++first;

}

}

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

Встроенные указатели, использующиеся с массивами, удовлетворяют соответствующим требованиям

int a[100] ;

// ... Код для сохранения значений в а[0], . .., а[99]

// Замена всех элементов массива, равных 5, на 6:

replace(&а[0], &а[100], 5, 6);

Поскольку тип deque<T>: : iterator также удовлетворяет всем требованиям к однонаправленным итераторам, этот алгоритм можно использовать и для замены элементов в деке:

deque<char> deque1;

// ... Код для вставки символов в dequel

// Замена всех 'е’ в dequel на 'о’:

replace(deque1.begin(), deque1.end(), 'e', 'o');

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