Стандартная библиотека C++<iterator>

В стандартной библиотеке C++,<iterator>Заголовочный файл предоставляет набор инструментов для обхода элементов в контейнерах. Итераторы — одна из основных концепций стандартной библиотеки шаблонов C++ (STL), позволяющая программистам единообразно получать доступ к элементам в контейнерах, не беспокоясь о конкретных деталях реализации контейнера.

Итератор — это объект, предоставляющий способ обхода элементов в контейнере. Итератор можно рассматривать как указатель на элемент в контейнере, но он более гибкий и мощный, чем указатель. Итераторы можно использовать для доступа к элементам в контейнере и их изменения, а также совместно с алгоритмами STL.

Итераторы в основном делятся на следующие категории:

  1. Итератор ввода: может выполнять только одиночные операции чтения, не может выполнять операции записи.
  2. Итератор вывода: может выполнять только одиночные операции записи, не может выполнять операции чтения.
  3. Однонаправленный итератор: может выполнять операции чтения и записи, а также перемещаться вперёд.
  4. Двунаправленный итератор: в дополнение ко всем операциям однонаправленного итератора он также может перемещаться назад.
  5. Итератор произвольного доступа: в дополнение ко всем операциям двунаправленного итератора он также может выполнять произвольный доступ, например доступ к элементам по индексу.

Часто используемые функции (ключевой момент)

Функция Функция Пример Описание
std::advance(it, n) Переместить итератор вперёд на n шагов advance(it, 2); Изменит исходный итератор
std::distance(a, b) Вычислить расстояние между двумя итераторами distance(v.begin(), v.end()); Возвращает количество элементов
std::next(it, n) Вернуть новый итератор, продвинутый на n шагов auto it2 = next(it, 2); Рекомендуется, не изменяет исходное значение
std::prev(it, n) Вернуть новый итератор, сдвинутый назад на n шагов auto it2 = prev(it, 1); Поддерживается начиная с C++11

Адаптеры итераторов (очень важно)

Адаптеры итераторов могут изменять поведение итераторов, чтобы адаптировать их к различным сценариям использования.

Adapter Функция Пример
std::back_inserter Вставка в конец (вызов push_back) back_inserter(vec)
std::front_inserter Вставка в начало (вызов push_front) front_inserter(list)
std::inserter Вставка в указанную позицию inserter(vec, it)

Потоковые итераторы (настоящее спасение для упрощения ввода-вывода)

Type Функция Пример
std::istream_iterator Чтение данных из входного потока istream_iterator<int>(cin)
std::ostream_iterator Запись в выходной поток ostream_iterator<int>(cout, " ")

Синтаксис итераторов

Синтаксис итераторов обычно выглядит следующим образом:

#include &lt;iterator&gt;

// 使用迭代器遍历容器
for (ContainerType::iterator it = container.begin(); it != container.end(); ++it) {
    // 访问元素 *it
}

Пример

Ниже приведён пример использования<iterator>Заголовочные файлы и обход итераторовstd::vectorпример:

Пример

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() {
    // Создание контейнера vector и его инициализация
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // Перебор vector с использованием итераторов
    for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // Используйте ключевое слово auto для упрощения типов итераторов
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // Используйте диапазонный цикл for из C++11
    for (int elem : vec) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // Используйте back_inserter для автоматической вставки
    std::vector<int> v2;
    std::fill_n(std::back_inserter(v2), 3, 100);

    // Используйте ostream_iterator для вывода
    std::copy(v2.begin(), v2.end(),
              std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

Вывод:

1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 
100 100 100 

Итог

<iterator>Основные функции можно свести к трём пунктам:

  • Унифицированный способ доступа: разные контейнеры используют один и тот же набор логики обхода.
  • Разделение контейнеров и алгоритмов: алгоритмы зависят только от итераторов.
  • Улучшенная переиспользуемость кода: один и тот же фрагмент кода можно применять к нескольким структурам данных.

Начинающим рекомендуется в первую очередь освоить следующее:

  • next / prev / distance
  • back_inserter
  • Метод обхода с помощью итератора
Другие расширения