Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторні роботи по програмуванні(14 лаб).doc
Скачиваний:
77
Добавлен:
16.05.2015
Размер:
1.43 Mб
Скачать

Ітератори

Одним з найважлівішіх елементів бібліотеки, поряд з контейнером и узагальнення алгоритмом - ітератор.

Ітератор являє собою клас, що забезпечує доступ до даніх іншого класу, тобто ітератор узагальнює поняття покажчика: він надає доступ до елементів контейнера без необхідності інкапсулювати контейнер. Аналогічно тому, як використовуються звичайні покажчики, ітератори можуть використовуватися для різних цілей. Ітератор може вказувати на конкретній об'єкт, пари ітераторів визначає діапазон об'єктів у послідовності (початок - кінець). При чому елементи послідовності випливають один за одним у логічній послідовності (у фізічній пам'яті вони розташовуються не обов'язково послідовно). Фізична реалізація порядку вибірки елементів з послідовності покладає на контейнери.

Внутрішній устрій ітератора може виглядати так:

class Iterator

{

T * pointer;

public:

T * GetPointer ()

{

return this -> pointer;

}

void SetPointer (T * pointer)

{

this -> pointer = pointer;

}

:

};

У STL існує три типи итераторов: iterator, reverse_iterator, і random access iterator. Для обходу колекції від меншого індексу до більшого, використовуються звичайні або forward ітератори. Для обходу колекції у зворотному напрямку використовуються reverse ітератори. Random access iterator є ітераторами, які можуть обходити колекцію як вперед, так і назад. Нижче наведено приклад використання итераторов для видалення половини елементів вектора:

# Include "stdafx.h"

# Include <iostream>

# Include <vector>

# Include <algorithm>

using namespace std;

void printInt (int number);

int _main (int argc, _TCHAR * argv [])

{

vector <int> myVec;

vector <int> :: iterator first, last;

for (long i = 0; i <10; i + +)

{

myVec.push_back (i);

}

first = myVec.begin ();

last = myVec.begin () + 5;

if (last> = myVec.end ())

{

return - 1;

}

myVec.erase (first, last);

for_each (myVec.begin (), myVec.end (), printInt);

return 0;

}

void printInt (int number)

{

cout << number << endl;

}

Важливо пам'ятати, що коли ви отримуєте ітератор до колекції, а після цього вносите колекцію, то цей ітератор стає вже непридатним до використання. Природно, не всі зміни призводять до непридатності ітератора для подальшого використання, а тільки зміни структури колекції. У разі ж, якщо ви просто зміните значення, збережені в колекції, то нічого страшного не станеться і ітератор не зіпсується.

Ітерація по колекції вперед відбувається так:

for (iterator element = begin (); element <end (); element + +)

{

t = (* element);

}

Ітерація по колекції назад відбувається так:

for (reverse_iterator element = rbegin (); element <rend ();

element + +)

{ t = (* element); }

Якщо ви працюєте і з random access iterator ітератором, то синтаксис конструкції може бути, наприклад, таким:

for (iterator element = begin (); element <end ();

element + = 2)

{

t = (* element);

}

Для більш ефективного використання контейнерів використовуйте typedef або наслідуйте свій клас від класу колекції.

Зробити це можна так:

typedef vector <int> myVector

typedef map <string, int> myMap

typedef deque <string> myQue

Або ось така техніка в разі спадкування:

class myVector: public vector <int> {};

У випадку з ітератором застосовна попередня техніка:

typedef myVector :: iterator vectorIterator

typedef myVector :: reverse_iterator revVectorIterator