Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
STL5 / lab4-iterators / lab4-iterators.doc
Скачиваний:
13
Добавлен:
10.04.2015
Размер:
299.01 Кб
Скачать

Использование итераторов

Каждая коллекция в библиотеке STL(как то:vector, list, queue, deque, map, setи т.д.) предоставляет итераторы для перебора своих элементов. Рассмотрим на конкретном примере:

#include <vector>

#include <iostream>

#include <list>

using namespace std;

template<class iterator>

void print(iterator start, iterator end) // (12)

{

cout<<"-----\n";

for(iterator i=start; i!=end; ++i) // (13)

{

cout<<(*i)<<"\n";

}

cout<<"Done\n";

}

intmain() {

int a[5]={1,2,3,4,5};

vector<int> v(&a[0], &a[5]); // (1)

vector<int>::iterator i; // (2)

list<int> l(v.begin(), v.end()); // (3)

print(v.begin(), v.end()); // (4)

print(l.begin(), l.end()); // (5)

print(v.begin()+1, v.end()); // (6)

print(&a[2], &a[3]); // (7)

print(v.rbegin(), v.rend()); // (8)

vector<int>::const_iterator j=v.begin()+2; // (9)

cout<<"3rd element: "<<(*j)<<"\n"; // (10)

// *j=38; // (11)

return 0;

}

Вывод программы:

-----

1

2

3

4

5

Done

-----

1

2

3

4

5

Done

-----

2

3

4

5

Done

-----

3

Done

-----

5

4

3

2

1

Done

3rd element: 3

Теперь комментарии.

Для начала рассмотрим функцию main.

(1): Создаем vectorиз массива. В классеvectorопределен конструктор:

vector(InputIteratorfirst,InputIteratorlast);

Поскольку &a[0]и&a[5]удовлетворяют всем требованиям итератора ввода, то возможен такой вызов конструктора.

(2): Создаем итератор. В каждом классе коллекций STLопределено несколько типов итераторов, предоставляемых этой коллекцией. В частности, классvectorв этом отношении наиболее универсален и предоставляет следующие типы:const_iterator, const_reverse_iterator, iterator, reverse_iterator.Назначения этих типов итераторов ясны из их названия. Простой классvector<int>::iterator представляет собой изменяемый итератор произвольного доступа.

(3): Создаем список, содержащий те же элементы, что и вектор. v.begin()иv.end()возвращают соответственно итератор, указывающий на первый элемент вектора и на законечный элемент. Классlist также предоставляет возможность конструирования из диапазона итераторов:

list(InputIterator first, InputIterator last);

Уже становится заметна универсальность STLи полезность итераторов: если бы такой возможности не было предоставлено, нам бы пришлось самим писать цикл вставки по одному элементу в список. Гораздо хуже было бы, если бы мы пытались создать, к примеру, список элементов не вектора, а словаря (map) или множества (set) – перебор их элементов крайне нетривиален.

(4): вызываем printдля всего вектора

(5): вызываем printдля всего списка. Как видно, вызовы выглядят абсолютно одинаково.

(6): Печатаем все элементы, кроме первого

(7): Печатаем элементы с 3 по 4 не включая 4. Опять вызов выглядит точно также.

Заметим, что вообще говоря передавая какой-либо функции диапазон итераторов, следует тем или иным образом гарантировать, что диапазон является корректным, т.е. jдостижим изi. В простых программах наподобие данной корректность или некорректность диапазона очевидна, однако в больших программах, где создание и обработка данных отстоят друг от друга в коде на значительное расстояние, следует внимательно относиться к теме корректности диапазонов итераторов.

(8): Используем несколько более интересные итераторы: функции vector::rbegin() иrend() возвращают итераторы, перебирающие элементы в обратном направлении.rbegin() указывает на последний элемент,rend() – на элемент перед первым (законечный в обратном направлении – или предначальный).

Обратите внимание, что v.begin()!=v.rend(), аv.end()!=v.rbegin(), они не только указывают на разные элементы, но и представляют собой объекты разных классов.

Проиллюстрировать это можно так:

begin()

end()

rbegin()

(9): Создаем константный итератор, указывающий на 3й элемент вектора.

(10): Доступ на чтение к константному итератору возможен

(11): А на запись – нет, поэтому написанное выражение бы вызвало ошибку компиляции, т.к. operator*() у классаvector<int>::const_iteratorвозвращаетconst int&.

(12): Объявляем функцию, способную работать с любым классом итераторов – печать элементов из некоторого диапазона. В частности, в строке (4) в качестве класса iterator подставляетсяvector<int>::iterator, а в строке (7) –int*.

(13): Видно, что для того, чтобы наша функция работала, необходимо и достаточно, чтобы класс iterator удовлетворял требованиям итератора ввода.

Соседние файлы в папке lab4-iterators