- •Итераторы
- •Основные понятия
- •Классификация итераторов
- •Свойства итераторов различных типов
- •Последовательные итераторы
- •Двунаправленные итераторы2
- •Итераторы произвольного доступа3
- •Итераторы ввода
- •Итераторы вывода
- •Использование итераторов
- •Вставка одного или нескольких элементов в позицию, указываемую итератором
- •Адаптеры итераторов и итераторы потоков ввода-вывода
- •Итераторы потоков ввода-вывода
- •Итераторы вставки (insert iterators).
- •Функции advance и distance
- •Теги и свойства итераторов5
- •Как написать свой итератор
Итераторы ввода
Использование:
InputIteratorit1;// Конструктор без аргументов
InputIteratorit2(it1);// Конструктор копий
it1=it2;// Оператор присваивания
if(it1==it2) {...}// Проверка на равенство. Равенство – лишь в том случае, когда it1 – копия it2 (полученная с помощью присваивания или конструктора копий), или наоборот.
if(it1!=it2) {...}// Неравенство – отрицание равенства
++it1;// Аналогично таким же операциям для последовательного итератора
it1++;
x=*it1; // Итератор ввода допускает чтение
// *it1=x – некорректно, т.к. итератор ввода не допускает записи
Скелет класса (это не точное объявление класса итератора из STL, однако оно позволяет понять, какие операции входят в интерфейс итератора):
classInputIterator
{
public:
// Конструктор копий
InputIterator(const InputIterator &i);
// Оператор присваивания
InputIterator& operator=(const InputIterator &i);
// B должен быть преобразуем к типу bool или просто является им
// Возвращает true тогда и только тогда, когда i - копия *this.
B operator==(const InputIterator &i);
B operator!=(const InputIterator &i) {return !(i==*this);}
// Операторы инкремента (продвижения, увеличения на единицу).
// Увеличиваемый итератор должен быть действительным (разыменовываемым).
// После увеличения он может быть либо остаться действительным,
// либо приобрести законечное значение.
// Префиксная форма оператора: ++x
// Напомним, что для итераторов ввода a==b не означает ++a==++b.
InputIterator&operator++(void);
// Постфиксная форма: x++
// Обычно после a=x++ a=старому значению х.
// Но поскольку после увеличения итератора старое значение
// недействительно, здесь возвращаемое значение запрещено
// использовать; его тип - void
voidoperator++(int);
// Итератор должен быть действительным.
// Если a - копия b, то *а эквивалентно *b.
constT&operator*();
};
Итераторы вывода
Использование:
OutputIterator it1;
OutputIterator it2(it1);
++it1;
it1++; // После предыдущей строчки эта операция некорректна; отдельно - допустима
*it1=x; // Итератор вывода допускает только запись
// x=*it1; - некорректно, итератор вывода не допускает чтения
Скелет класса (это не точное объявление класса итератора из STL, однако оно позволяет понять, какие операции входят в интерфейс итератора):
classOutputIterator
{
public:
// Конструктор копий.
// *a=t эквивалентно *OutputIterator(a)=t.
OutputIterator(const OutputIterator &i);
// Единственное законное использование итератора вывода -
// запись в указуемый элемент, т.е. вообще говоря класс Q
// должен быть объектом-курсором, допускающим запись (ровно
// однократную), но не допускающим чтение.
Qoperator*();
// Префиксная форма
OutputIterator operator++(void);
// Постфиксная форма
OutputIteratoroperator++(int);
};
Нетрудно заметить, что указатели языка С++ обладают всеми свойствами итераторов произвольного доступа, для них имеют смысл все операции, которые имеют смысл для итераторов произвольного доступа. Учитывая, что STLявляется шаблонной библиотекой,T*может быть использован в качестве итератора произвольного доступа, аconst T* в качестве константного итератора произвольного доступа.