- •Итераторы
- •Основные понятия
- •Классификация итераторов
- •Свойства итераторов различных типов
- •Последовательные итераторы
- •Двунаправленные итераторы2
- •Итераторы произвольного доступа3
- •Итераторы ввода
- •Итераторы вывода
- •Использование итераторов
- •Вставка одного или нескольких элементов в позицию, указываемую итератором
- •Адаптеры итераторов и итераторы потоков ввода-вывода
- •Итераторы потоков ввода-вывода
- •Итераторы вставки (insert iterators).
- •Функции advance и distance
- •Теги и свойства итераторов5
- •Как написать свой итератор
Вставка одного или нескольких элементов в позицию, указываемую итератором
Все стандартные последовательные контейнеры содержат следующие методы:
iterator insert(iterator where, const value_type &val);
Этот метод выполняет вставку элемента в позицию перед позицией, указываемой итератором where. Возвращаемое значение – итератор, указывающий на вставленный элемент.
void insert(iterator _Where, size_type _Count, const Type& _Val);
Вставка _Count элементов, равных _Val, в позицию перед позицией указываемой итератором _Where.
template<class InputIterator>
voidinsert(iterator _Where, InputIterator _First, InputIterator _Last);
Вставка элементов из диапазона определяемого парой итераторов [_First, _Last), в позицию перед позицией указываемой итератором _Where.
Пример из MSDN:
// list_class_insert.cpp
// compile with: /EHsc
#include <list>
#include <iostream>
intmain( )
{
using namespace std;
list <int> c1, c2;
list <int>::iterator Iter;
c1.push_back( 10 );
c1.push_back( 20 );
c1.push_back( 30 );
c2.push_back( 40 );
c2.push_back( 50 );
c2.push_back( 60 );
cout << "c1 =";
for ( Iter = c1.begin( ); Iter != c1.end( ); Iter++ )
cout << " " << *Iter;
cout << endl;
Iter = c1.begin( );
Iter++;
c1.insert( Iter, 100 );
cout << "c1 =";
for ( Iter = c1.begin( ); Iter != c1.end( ); Iter++ )
cout << " " << *Iter;
cout << endl;
Iter = c1.begin( );
Iter++;
Iter++;
c1.insert( Iter, 2, 200 );
cout << "c1 =";
for ( Iter = c1.begin( ); Iter != c1.end( ); Iter++ )
cout << " " << *Iter;
cout << endl;
c1.insert( ++c1.begin( ), c2.begin( ),--c2.end( ) );
/* Помним, что хотя в этой программе и очевидно, что
* [c2.begin(), --c2.end()) – корректный диапазон, в общем случае
* следовало бы проверить это отдельно. Это условие может нарушиться,
* например, если в c2 нет элементов – тогда c2.end() и c2.begin()
* будут указывать на один и тот же фиктивный элемент, а –-c2.end()
* будет лежать _перед_ c2.begin(): таким образом, диапазон будет
* некорректен
*/
cout << "c1 =";
for ( Iter = c1.begin( ); Iter != c1.end( ); Iter++ )
cout << " " << *Iter;
cout << endl;
}
Вывод программы:
c1 = 10 20 30
c1 = 10 100 20 30
c1 = 10 100 200 200 20 30
c1 = 10 40 50 100 200 200 20 30
Итак:
Все STL-коллекции предоставляют итераторыbegin() иend(). Чтобы перебрать элементы любой коллекции, следует написать примерно следующее (псевдокод):
collection<T> c;
collection<T>::iterator сend;
// как-то заполнить коллекцию
cend=c.end();
// Перебор всех элементов коллекции
for(collection<T>::iterator i=c.begin(); i!=cend; ++i) { // (*)
f(*i); // Сделать что-нибудь с очередным элементом
}
Адаптеры итераторов и итераторы потоков ввода-вывода
Адаптер итератора – это «надстройка» над обычным итератором, обладающая тем же самым интерфейсом, но выполняющая какие-то другие или более сложные действия.
Например, reverse_iteratorявляется адаптером дляiteratorпозволяющим просматривать коллекцию в обратном порядке. То есть, обратный итератор, созданный из прямого (обязательно двунаправленного или произвольного доступа), будет при операции ++ вызывать у вложенного объекта – прямого итератора – операцию --, и т.д.
Наиболее важные из адаптеров – итераторы потоков ввода-вывода и итераторы вставки.