Урок №206. Ітератори STL

  Юрій  | 

  Оновл. 20 Кві 2021  | 

 99

На попередньому уроці ми розглянули контейнери STL, а сьогодні розглянемо ітератори STL.

Ітератор — це об’єкт, здатний перебирати елементи контейнерного класу без необхідності користувачеві знати реалізацію цього контейнерного класу. У багатьох контейнерах (особливо в списку і в асоціативних контейнерах) ітератори є основним способом доступу до елементів цих контейнерів.

Функціонал ітераторів

Про ітератор можна думати, як про вказівник на певний елемент контейнерного класу з додатковим набором перевантажених операторів для виконання чітко визначених функцій:

   Оператор * — повертає елемент, на який в даний момент вказує ітератор.

   Оператор ++ — переміщує ітератор до наступного елементу контейнера. Більшість ітераторів також надають оператор −− для переходу до попереднього елемента.

   Оператори == і != — використовуються для визначення того, чи вказують обидва ітератори на один і той же елемент чи ні. Для порівняння значень, на які вказують обидва ітератори, потрібно спочатку розіменувати ці ітератори, а потім використати оператор == або оператор !=.

   Оператор = — присвоює ітератору нову позицію (зазвичай початковий або кінцевий елемент контейнера). Щоб присвоїти значення елемента, на який вказує ітератор, іншому об’єкту, потрібно спочатку розіменувати ітератор, а потім використати оператор =.

Кожний контейнерний клас має 4 основні методи для роботи з оператором =:

   метод begin() — повертає ітератор, який представляє початковий елемент контейнера;

   метод end() — повертає ітератор, який представляє елемент, який знаходиться після останнього елемента в контейнері;

   метод cbegin() — повертає константний (тільки для читання) ітератор, який представляє початковий елемент контейнера;

   метод cend() — повертає константний (тільки для читання) ітератор, який представляє елемент, що знаходиться після останнього елемента в контейнері.

Може здатися дивним, що метод end() не вказує на останній елемент контейнера, але це зроблено з метою спрощення використання циклів: цикл перебирає елементи до тих пір, поки ітератор не досягне методу end(), і тоді вже все — «Баста!» .

Нарешті, всі контейнери надають (як мінімум) два типи ітераторів:

   container::iterator — ітератор для читання/запису;

   container::const_iterator — ітератор тільки для читання.

Розглянемо кілька прикладів використання ітераторів.

Ітерація по вектору

Заповнимо вектор 5-ма числами і за допомогою ітераторів виведемо значення вектора на екран:

Результат виконання програми:

0 1 2 3 4

Ітерація по списку

Виконаємо все те саме, що вище, але вже зі списком:

Результат виконання програми:

0 1 2 3 4

Зверніть увагу, код цієї програми майже ідентичний попередньому прикладу, хоча реалізація векторів і списків значно відрізняється!

Ітерація по set-у

У наступній програмі ми створимо set з 5 чисел і, використовуючи ітератор, виведемо ці значення на екран:

Результат виконання програми:

-4 2 3 8 9

Зверніть увагу, хоча заповнення set-у елементами відрізняється від способу заповнення вектора і списку вище, але код, який використовується для перебору елементів set-у, ідентичний.

Ітерація по асоціативному масиву

Цей приклад трохи складніший. Контейнери map і multimap приймають пари елементів (визначені як std::pair). Ми використаємо допоміжну функцію make_pair() для створення пар. std::pair дозволяє отримати доступ до елементу (до пари “ключ-значення”) через перший і другий члени. У нашому асоціативному масиві ми використаємо перший член в якості “ключа”, а другий в якості “значення”:

Результат виконання програми:

1=spider 2=dog 3=cat 4=lion 5=chicken

Зверніть увагу, наскільки легко за допомогою ітераторів перебирати елементи контейнерів. Вам не потрібно турбуватися про те, як асоціативний масив зберігає свої дані!

Висновки

Ітератори надають простий спосіб перебору елементів контейнерного класу без необхідності знати реалізацію цього контейнерного класу. У поєднанні з алгоритмами STL і методами контейнерних класів ітератори стають ще потужнішими.

Варто відзначити ще один момент: ітератори повинні бути реалізовані для кожного контейнера окремо, оскільки ітератор повинен знати реалізацію контейнерного класу. Таким чином, ітератори завжди прив’язані до конкретних контейнерних класів.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (Немає Оцінок)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *