§ 14. Пераўтварэнне элементаў масіву

14.4. Паняцце ітэратара

Ітэратар — абагульнены паказальнік [1], які дазваляе карыстальніку перабіраць без неабходнасці ведаць, як рэалізаваны сам кантэйнер.

Вектар з’яўляецца кантэйнерам, у якім рэалізаваны паслядоўны доступ да элементаў, ітэратар дазваляе абысці ўсе элементы вектара, перамяшчэнне адбываецца элемент за элементам. Ітэратары дазваляюць звяртацца да элементаў вектара без выкарыстання індэксаў.

Для вектара вызначаны стандартныя ітэратары begin() і end(). Итэратар begin() паказвае на першы элемент у вектары. Ітэратар end() — на месца пасля апошняга элемента вектара.

Для любога ітэратара (it) даступныя наступныя аперацыі (прыклад 14.6):

  • інкрэмент (it++) — для доступу да наступнага элемента;
  • разнайменне (*it) — для атрымання значэння элемента;
  • аператары роўнасці (it1 = = it2) і няроўнасці (it1 != it2) для вызначэння таго, ці супадаюць два ітэратары.

Для вектара ітэратар забяспечвае дадатковую функцыянальнасць:

  • дабаўленне канстанты (it += 20 зрушыцца на 20 элементаў наперад);
  • адлегласць паміж ітэратарамі 
    (int dist = it2 - it1).

Пачынаючы са стандарта C++11, абход вектара з дапамогай 

vector <int> a(n);

for (auto i: a)

  cout << i << " ";

Пераменная i, тып якой вызначаецца аўтаматычна, будзе па чарзе атрымліваць значэнні элементаў вектара. Такім чынам можна атрымаць значэнні элементаў вектара, але немагчыма атрымаць індэкс элемента. Такі цыкл называюць цыклам foreach, або цыклам, заснаваным на дыяпазоне.


[1] Паказальнік — пераменная, якая абазначае адрас памяці. Паказальнік  прызначаны для прамога звароту па адрасе памяці да аб’екта, які размешчаны па гэтым адрасе.

Для вектара вызначаны таксама рэверсіўныя (адваротныя) ітэратары, якія дазваляюць перабіраць элементы кантэйнера ў адваротным напрамку. Для атрымання рэверсіўнага ітэратара ўжываюцца функцыі rbegin() і rend(). Итэратар rbegin()паказвае на канец бягучага вектара, а ітэратар rend() — на пачатак вектара.

Прыклад 14.6. Аперацыі з ітэратарам

vector <int> a = {1, 2, 3, 5, 9};

vector <int> :: iterator it;

Разгледзім аперацыю:

int x;

it = a.begin();

= *it;

cout << x << endl;

Ітэратар it паказвае на пачатак вектара. Значэнне пераменнай x — значэнне элемента вектара, на які паказвае ітэратар. Будзе выведзена значэнне 1.

it++;

cout << *it << endl;

Ітэратар зрушыўся на адзін элемент і цяпер паказвае на элемент з індэксам 1, будзе выведзена значэнне 2.

it = a.begin() + 3;

cout << *it << endl;

Ітэратар зрушыўся на 3 элементы ад пачатку і паказвае на элемент з індэксам 3, будзе выведзена значэнне 5.

if (it == a.begin())

  cout << boolalpha << true;

else

  cout << boolalpha << false;

Пасля папярэдняй аперацыі ітэратар паказвае на элемент з індэксам 3, таму будзе выведзена false.

int dist1 = it - a.begin();

int dist2 = a.end() - a.begin();

cout <<  dist1 << endl;

cout <<  dist2 << endl;

Будуць выведзены значэнні 3 і 5. Значэнне 5 — колькасць элементаў у вектары.

Цыклу foreach адпавядае наступны запіс цыкла for:

vector <int> :: iterator i;

for (= a.begin();

     i != a.end();

     i++)

  cout << *<< " ";

або

  cout << "a % b = " << d << endl;

  cout << "a % b = " << d << endl;

for (auto= a.begin();

  cout << "a % b = " << d << endl;

     i != a.end();

     i++)

  cout << *<< " ";