Sobes.tech
Junior
178
questionbank

Какие виды итераторов ты знаешь?

Ответ от нейросети

sobes.tech AI

Итераторы в C++ представляют собой обобщенные указатели, предоставляющие доступ к элементам контейнера и возможность их обхода. Согласно стандарту C++, различают 5 основных категорий итераторов, упорядоченных по возрастанию их возможностей:

  • Input iterators (Входные итераторы):
    • Позволяют только чтение элементов (operator*() const).
    • Позволяют инкрементировать итератор (operator++()).
    • Поддерживают сравнение на равенство (operator==(), operator!=()).
    • Пример: итераторы для потоков ввода (std::istream_iterator).
  • Output iterators (Выходные итераторы):
    • Позволяют только запись элементов (operator*()).
    • Позволяют инкрементировать итератор (operator++()).
    • Пример: итераторы для потоков вывода (std::ostream_iterator).
  • Forward iterators (Однонаправленные итераторы):
    • Поддерживают все возможности входных и выходных итераторов.
    • Гарантируют, что инкрементирование итератора всегда ведет к следующему элементу или концу последовательности.
    • Пример: итераторы для односвязных списков (std::forward_list).
  • Bidirectional iterators (Двунаправленные итераторы):
    • Поддерживают все возможности однонаправленных итераторов.
    • Позволяют декрементировать итератор (operator--()) для перемещения к предыдущему элементу.
    • Пример: итераторы для списков (std::list) и множеств (std::set).
  • Random access iterators (Итераторы произвольного доступа):
    • Поддерживают все возможности двунаправленных итераторов.
    • Позволяют выполнять арифметические операции с итераторами (сложение/вычитание целых чисел, вычитание итераторов) для быстрого перехода к любому элементу.
    • Позволяют использовать оператор [] для доступа к элементам по индексу.
    • Пример: итераторы для векторов (std::vector) и массивов (std::array).

Эта иерархия подразумевает, что каждая последующая категория итераторов обладает возможностями всех предыдущих. Например, итератор произвольного доступа также является двунаправленным, однонаправленным, входным и выходным.

#include <vector>
#include <list>
#include <forward_list>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    // Random access iterator
    auto vec_it = vec.begin();
    vec_it += 2; // Произвольный доступ
    std::cout << *vec_it << std::endl; // Вывод: 3

    std::list<int> lst = {10, 20, 30};
    // Bidirectional iterator
    auto list_it = lst.begin();
    ++list_it; // Инкремент
    --list_it; // Декремент

    std::forward_list<int> flst = {100, 200, 300};
    // Forward iterator
    auto flist_it = flst.begin();
    ++flist_it; // Только инкремент

    // Input iterator
    std::istream_iterator<int> input_it(std::cin);
    // Output iterator
    std::ostream_iterator<int> output_it(std::cout, " ");

    return 0;
}

Существуют также адаптеры итераторов (например, std::reverse_iterator, std::move_iterator), которые изменяют поведение базовых итераторов.