На этом шаге мы рассмотрим особенности использования обратных итераторов.
Третей разновидностью итераторных адаптеров STL являются обратные итераторы. Эти итераторы работают в противоположном направлении: вызов оператора ++ на внутреннем уровне преобразуется в вызов оператора --, и наоборот. Все контейнеры поддерживают создание обратных итераторов функциями rbegin() и rend(). Рассмотрим следующий пример:
//--------------------------------------------------------------------------- #include <vcl.h> #include <iostream> #include <iterator> #include <vector> #include <string> #include <algorithm> #include <conio.h> //необходимо для getch() #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused using namespace std; std::string ToRus(const std::string &in) { char *buff = new char [in.length()+1]; CharToOem(in.c_str(),buff); std::string out(buff); delete [] buff; return out; } int main(int argc, char* argv[]) { vector<int> coll; vector<int>::iterator pos; // Вставка элементов со значениями от 1 до 9 for (int i=1; i<=9; ++i) { coll.push_back(i); } cout << ToRus("Элементы вектора:\n"); for (pos = coll.begin(); pos != coll.end(); ++pos) { cout << *pos << ' '; } cout << endl; // Вывод всех элементов в обратном порядке cout << ToRus("Элементы вектора в обратном порядке:\n"); copy (coll.rbegin(), coll.rend(), // Источник ostream_iterator<int>(cout," ")); // Приемник cout cout << endl; getch(); return 0; } //---------------------------------------------------------------------------
Выражение coll.rbegin() возвращает обратный итератор для коллекции coll. Полученный итератор может использоваться, чтобы начать обратный перебор элементов коллекции, поскольку он устанавливается на последний элемент коллекции. Таким образом, выражение *coll.rbegin() возвращает значение последнего элемента.
Соответственно выражение coll.rend() возвращает обратный итератор для коллекции coll, который может использоваться для завершения перебора в обратном направлении. По аналогии с обычными интервалами он устанавливается за концом интервала, но в противоположном направлении - то есть перед первым элементом коллекции.
Значение выражения *coll.rend() не определено, как, впрочем, и значение *coll.end(). Никогда не используйте операторы * и -> с позициями, не представляющими реальных элементов коллекции.
Основное достоинство обратных итераторов заключается в том, что все алгоритмы получают возможность работать в обратном направлении без модификации кода. Переход к следующему элементу оператором ++ преобразуется в переход к предыдущему элементу оператором --. В нашем примере алгоритм сору() перебирает все элементы coll от последнего к первому, поэтому результат работы программы выглядит так:
Рис.1. Результат работы приложения
"Нормальные" итераторы можно переключать в режим обратного перебора и наоборот. Однако следует помнить, что при этом изменяется текущий элемент, связанный с итератором.
Со следующего шага мы начнем знакомиться с модифицирующими алгоритмами.