Библиотека итераторов
Итераторы — это обобщение указателей, позволяющее программе на C++ работать с различными структурами данных (например, контейнерами и диапазонами(начиная с C++20)) единообразным способом. Библиотека итераторов предоставляет определения итераторов, а также характеристики итераторов, адаптеры и вспомогательные функции.
Поскольку итераторы являются абстракцией указателей, их семантика обобщает большую часть семантики указателей в C++. Это гарантирует, что любой шаблон функции, принимающий итераторы, будет также работать с обычными указателями.
Категории итераторов
Существует пять(до C++17)шесть(начиная с C++17) видов итераторов: LegacyInputIterator, LegacyOutputIterator, LegacyForwardIterator, LegacyBidirectionalIterator, LegacyRandomAccessIterator и LegacyContiguousIterator(начиная с C++17). (См. также LegacyIterator — самую базовую категорию итераторов.)
Категории итераторов определяются не конкретными типами, а операциями, которые можно с ними выполнять. Это определение означает, что в качестве итератора можно использовать любой тип, поддерживающий необходимые операции. Например, указатель поддерживает все операции, требуемые для LegacyRandomAccessIterator, поэтому указатель можно использовать везде, где ожидается LegacyRandomAccessIterator.
Все категории итераторов (кроме LegacyOutputIterator) можно организовать в иерархию, в которой более мощные категории итераторов (например, LegacyRandomAccessIterator) поддерживают операции менее мощных категорий (например, LegacyInputIterator). Если итератор относится к одной из этих категорий и также удовлетворяет требованиям LegacyOutputIterator, он называется изменяемым итератором и поддерживает как ввод, так и вывод. Неизменяемые итераторы называются константными.
| Итераторы называются итераторами constexpr, если все операции, необходимые для выполнения требований категории итератора, являются функциями constexpr. | (начиная с C++20) |
| Категория итератора | Операции и требования к хранилищу | ||||||
|---|---|---|---|---|---|---|---|
| запись | чтение | инкремент | декремент | произвольный доступ | непрерывное хранение |
||
| без многократных проходов | с многократными проходами |
||||||
| LegacyIterator | Обязательно | ||||||
| LegacyOutputIterator | Обязательно | Обязательно | |||||
|
LegacyInputIterator (изменяемый, если поддерживает операцию записи) | Обязательно | Обязательно | |||||
|
LegacyForwardIterator (также удовлетворяет требованиям LegacyInputIterator) | Обязательно | Обязательно | Обязательно | ||||
|
LegacyBidirectionalIterator (также удовлетворяет требованиям LegacyForwardIterator) | Обязательно | Обязательно | Обязательно | Обязательно | |||
|
LegacyRandomAccessIterator (также удовлетворяет требованиям LegacyBidirectionalIterator) | Обязательно | Обязательно | Обязательно | Обязательно | Обязательно | ||
| LegacyContiguousIterator[1] (также удовлетворяет требованиям LegacyRandomAccessIterator) | Обязательно | Обязательно | Обязательно | Обязательно | Обязательно | Обязательно | |
- Категория LegacyContiguousIterator была формально специфицирована только в C++17, однако итераторы
std::vector,std::basic_string,std::arrayиstd::valarray, а также указатели на элементы массивов C часто рассматриваются как отдельная категория в коде до C++17.
Примечание: тип, поддерживающий операции, указанные в строке таблицы выше, не обязательно относится к соответствующей категории; полный перечень требований см. на странице этой категории.
Определения
Типы и возможность записи
Итератор ввода i поддерживает выражение *i, результатом которого является значение некоторого объектного типа T, называемого типом значения итератора.
Итератор вывода i имеет непустое множество типов, которые являются доступными для записи(до C++20)indirectly_writable(начиная с C++20) через итератор; для каждого такого типа T выражение *i = o является допустимым, где o — значение типа T.
Для каждого типа итератора X для которого определено равенство(до C++20) существует соответствующий знаковый тип целого числа(до C++20)целочисленный-подобный(начиная с C++20) тип, называемый типом разности итератора.
Разыменовываемость и корректность
Подобно тому как обычный указатель на массив гарантирует наличие значения указателя, указывающего за последний элемент массива, для любого типа итератора существует значение итератора, указывающее за последний элемент соответствующей последовательности. Такое значение называется значением за концом.
Значения итератора i, для которых определено выражение *i, называются разыменовываемыми. Стандартная библиотека никогда не предполагает, что значения за концом являются разыменовываемыми.
Итераторы также могут иметь сингулярные значения, не связанные ни с какой последовательностью. Результаты большинства выражений для сингулярных значений не определены; исключениями являются только
- присваивание несингулярного значения итератору, содержащему сингулярное значение,
- уничтожение итератора, содержащего сингулярное значение, и
- для итераторов, удовлетворяющих требованиям DefaultConstructible, использование инициализированного значением итератора в качестве источника операции копирования или перемещения(начиная с C++11).
В этих случаях сингулярное значение перезаписывается так же, как любое другое значение. Разыменовываемые значения всегда являются несингулярными.
Недействительный итератор — это итератор, который может быть сингулярным.
Диапазоны
Большинство шаблонов алгоритмов стандартной библиотеки, работающих со структурами данных, имеют интерфейсы, использующие диапазоны.
| Итератор Диапазон — это пара итераторов, обозначающих начало и конец вычисления. Диапазон Диапазон | (до C++20) |
| Диапазон может быть представлен одним из следующих способов:
Диапазон «итератор — сторожевое значение»Итератор и сторожевое значение, обозначающие диапазон, можно сравнивать. Сторожевое значение Если Диапазон с заданным количеством элементовДиапазон с заданным количеством элементов Диапазон с заданным количеством элементов
| (начиная с C++20) |
Результат применения функций стандартной библиотеки к некорректным диапазонам не определён.
Концепты итераторов (начиная с C++20)
Новая система итераторов основана на концептах, отличающихся от итераторов C++17. Хотя основная классификация осталась похожей, требования к отдельным категориям итераторов несколько изменились.
Определено в пространстве имён std |
|
|---|---|
|
(C++20) | задаёт требования к типу, косвенно читаемому с помощью оператора * (концепт) |
|
(C++20) | задаёт требования, согласно которым значение можно записать в объект, на который ссылается итератор (концепт) |
|
(C++20) | задаёт требования, согласно которым тип semiregular можно инкрементировать с помощью операторов префиксного и постфиксного инкремента (концепт) |
|
(C++20) | задаёт требования, согласно которым операция инкремента для типа weakly_incrementable сохраняет равенство, а сам тип является equality_comparable (концепт) |
|
(C++20)(C++20) | задаёт требования, согласно которым тип ведёт себя как (знаковый) целочисленный тип (концепт, используемый только для описания*) |
|
(C++20) | задаёт требования, согласно которым объекты типа можно инкрементировать и разыменовывать (концепт) |
|
(C++20) | задаёт требования, согласно которым тип является сторожевым значением для типа input_or_output_iterator (концепт) |
|
(C++20) | задаёт требования, согласно которым оператор - можно применить к итератору и сторожевому значению для вычисления их разности за постоянное время (концепт) |
|
(C++20) | задаёт требования, согласно которым тип является итератором ввода, то есть значения, на которые он ссылается, можно читать, а сам итератор можно инкрементировать как префиксным, так и постфиксным оператором (концепт) |
|
(C++20) | задаёт требования, согласно которым тип является итератором вывода для заданного типа значения, то есть значения этого типа можно записывать через него, а сам итератор можно инкрементировать как префиксным, так и постфиксным оператором (концепт) |
|
(C++20) | задаёт требования, согласно которым input_iterator является итератором прямого хода, поддерживающим сравнение на равенство и многократный проход (концепт) |
|
(C++20) | задаёт требования, согласно которым forward_iterator является двунаправленным итератором, поддерживающим перемещение назад (концепт) |
|
(C++20) | задаёт требования, согласно которым bidirectional_iterator является итератором произвольного доступа, поддерживающим перемещение за постоянное время и индексирование (концепт) |
|
(C++20) | задаёт требования, согласно которым random_access_iterator является непрерывным итератором, указывающим на элементы, расположенные в памяти непрерывно (концепт) |
Связанные типы итераторов (начиная с C++20)
Определено в пространстве имён std |
|
|---|---|
|
(C++20) | вычисляет тип разности типа weakly_incrementable (шаблон класса) |
|
(C++20) | вычисляет тип значения типа indirectly_readable (шаблон класса) |
|
(C++20)(C++20)(C++23)(C++20)(C++20)(C++20) | вычисляет связанные типы итератора (шаблон псевдонима) |
Примитивы итераторов
| предоставляет единый интерфейс к свойствам итератора (шаблон класса) |
|
|
(C++20) | пустые типы классов, используемые для обозначения категорий итераторов (класс) |
|
(устарел в C++17) | базовый класс, упрощающий определение необходимых типов для простых итераторов (шаблон класса) |
Точки настройки итераторов (начиная с C++20)
Определено в пространстве имён std::ranges |
|
|---|---|
|
(C++20) | преобразует результат разыменования объекта в соответствующий тип rvalue-ссылки (объект точки настройки) |
|
(C++20) | меняет местами значения, на которые ссылаются два разыменовываемых объекта (объект точки настройки) |
Концепты и вспомогательные средства алгоритмов (начиная с C++20)
Набор концептов и связанных с ними вспомогательных шаблонов, предназначенных для упрощения задания ограничений на распространённые операции алгоритмов.
Определено в заголовочном файле <iterator> |
|
|---|---|
Определено в пространстве имён std |
|
Косвенные вызываемые концепции |
|
|
(C++20)(C++20) | задаёт требование, согласно которому вызываемый тип можно вызвать с результатом разыменования типа indirectly_readable (концепция) |
|
(C++20) | задаёт требование, согласно которому вызываемый тип при вызове с результатом разыменования типа indirectly_readable удовлетворяет требованиям predicate (концепция) |
|
(C++20) | задаёт требование, согласно которому вызываемый тип при вызове с результатами разыменования двух типов indirectly_readable удовлетворяет требованиям predicate (концепция) |
|
(C++20) | задаёт требование, согласно которому вызываемый тип при вызове с результатами разыменования двух типов indirectly_readable удовлетворяет требованиям equivalence_relation (концепция) |
|
(C++20) | задаёт требование, согласно которому вызываемый тип при вызове с результатами разыменования двух типов indirectly_readable удовлетворяет требованиям strict_weak_order (концепция) |
Общие требования к алгоритмам |
|
|
(C++20) | задаёт требование, согласно которому значения можно перемещать из типа indirectly_readable в тип indirectly_writable (концепция) |
|
(C++20) | задаёт требование, согласно которому значения можно перемещать из типа indirectly_readable в тип indirectly_writable, причём перемещение может выполняться через промежуточный объект (концепция) |
|
(C++20) | задаёт требование, согласно которому значения можно копировать из типа indirectly_readable в тип indirectly_writable (концепция) |
|
(C++20) | задаёт требование, согласно которому значения можно копировать из типа indirectly_readable в тип indirectly_writable, причём копирование может выполняться через промежуточный объект (концепция) |
|
(C++20) | задаёт требование, согласно которому значения, на которые ссылаются два типа indirectly_readable, можно обменять местами (концепция) |
|
(C++20) | задаёт требование, согласно которому значения, на которые ссылаются два типа indirectly_readable, можно сравнивать (концепция) |
|
(C++20) | задаёт общие требования к алгоритмам, переставляющим элементы на месте (концепция) |
|
(C++20) | задаёт требования к алгоритмам, объединяющим отсортированные последовательности в выходную последовательность путём копирования элементов (концепция) |
|
(C++20) | задаёт общие требования к алгоритмам, преобразующим последовательности в упорядоченные последовательности путём перестановки элементов (концепция) |
Утилиты |
|
|
(C++20) | вычисляет результат вызова вызываемого объекта с результатами разыменования некоторого набора типов indirectly_readable(шаблон псевдонима) |
|
(C++20) | вспомогательный шаблон для задания ограничений алгоритмов, принимающих проекции (шаблон класса) |
|
(C++26) | вычисляет тип значения типа indirectly_readable посредством проекции(шаблон псевдонима) |
Адаптеры итераторов
| адаптер итератора для обхода в обратном порядке (шаблон класса) |
|
|
(C++14) | создаёт std::reverse_iterator типа, выводимого из аргумента (шаблон функции) |
| адаптер итератора для вставки в конец контейнера (шаблон класса) |
|
создаёт std::back_insert_iterator типа, выводимого из аргумента (шаблон функции) |
|
| адаптер итератора для вставки в начало контейнера (шаблон класса) |
|
создаёт std::front_insert_iterator типа, выводимого из аргумента (шаблон функции) |
|
| адаптер итератора для вставки в контейнер (шаблон класса) |
|
создаёт std::insert_iterator типа, выводимого из аргумента (шаблон функции) |
|
|
(C++23) | адаптер итератора, преобразующий итератор в константный итератор (шаблон класса) |
|
(C++23) | вычисляет тип константного итератора для заданного типа (шаблон псевдонима) |
|
(C++23) | вычисляет тип sentinel, используемый с константными итераторами (шаблон псевдонима) |
|
(C++23) | создаёт std::const_iterator типа, выводимого из аргумента (шаблон функции) |
|
(C++23) | создаёт std::const_sentinel типа, выводимого из аргумента (шаблон функции) |
|
(C++11) | адаптер итератора, разыменование которого даёт rvalue (шаблон класса) |
|
(C++20) | адаптер sentinel для std::move_iterator (шаблон класса) |
|
(C++11) | создаёт std::move_iterator типа, выводимого из аргумента (шаблон функции) |
|
(C++20) | адаптирует тип итератора и его sentinel к общему типу итератора (шаблон класса) |
|
(C++20) | sentinel по умолчанию для итераторов, знающих границу своего диапазона (класс) |
|
(C++20) | адаптер итератора, отслеживающий расстояние до конца диапазона (шаблон класса) |
|
(C++20) | sentinel, который всегда сравнивается неравным с любым типом weakly_incrementable (класс) |
Потоковые итераторы
входной итератор, считывающий данные из std::basic_istream (шаблон класса) |
|
выходной итератор, записывающий данные в std::basic_ostream (шаблон класса) |
|
входной итератор, считывающий данные из std::basic_streambuf (шаблон класса) |
|
выходной итератор, записывающий данные в std::basic_streambuf (шаблон класса) |
Операции с итераторами
Определено в заголовочном файле <iterator> |
|
|---|---|
| перемещает итератор на заданное расстояние (шаблон функции) |
|
| возвращает расстояние между двумя итераторами (шаблон функции) |
|
|
(C++11) | увеличивает итератор (шаблон функции) |
|
(C++11) | уменьшает итератор (шаблон функции) |
|
(C++20) | перемещает итератор на заданное расстояние или до заданной границы (функциональный объект алгоритма) |
|
(C++20) | возвращает расстояние между итератором и sentinel либо между началом и концом диапазона (функциональный объект алгоритма) |
|
(C++20) | увеличивает итератор на заданное расстояние или до заданной границы (функциональный объект алгоритма) |
|
(C++20) | уменьшает итератор на заданное расстояние или до заданной границы (функциональный объект алгоритма) |
Доступ к диапазону (начиная с C++11)
Эти шаблоны функций, не являющихся членами класса, предоставляют универсальный интерфейс для контейнеров, обычных массивов и std::initializer_list.
Определено в заголовочном файле <array> | ||
|---|---|---|
Определено в заголовочном файле <deque> | ||
Определено в заголовочном файле <flat_map> | (начиная с C++23) | |
Определено в заголовочном файле <flat_set> | (начиная с C++23) | |
Определено в заголовочном файле <forward_list> | ||
Определено в заголовочном файле <hive> | (начиная с C++26) | |
Определено в заголовочном файле <inplace_vector> | (начиная с C++26) | |
Определено в заголовочном файле <iterator> | ||
Определено в заголовочном файле <list> | ||
Определено в заголовочном файле <map> | ||
Определено в заголовочном файле <optional> | (начиная с C++26) | |
Определено в заголовочном файле <regex> | ||
Определено в заголовочном файле <set> | ||
Определено в заголовочном файле <span> | (начиная с C++20) | |
Определено в заголовочном файле <stacktrace> | (начиная с C++23) | |
Определено в заголовочном файле <string> | ||
Определено в заголовочном файле <string_view> | (начиная с C++17) | |
Определено в заголовочном файле <unordered_map> | ||
Определено в заголовочном файле <unordered_set> | ||
Определено в заголовочном файле <valarray> | ||
Определено в заголовочном файле <vector> |
Определено в пространстве имён std |
|
|---|---|
|
(C++11)(C++14) | возвращает итератор на начало контейнера или массива (шаблон функции) |
|
(C++11)(C++14) | возвращает итератор на конец контейнера или массива (шаблон функции) |
|
(C++14) | возвращает обратный итератор на начало контейнера или массива (шаблон функции) |
|
(C++14) | возвращает обратный итератор конца контейнера или массива (шаблон функции) |
|
(C++17)(C++20) | возвращает размер контейнера или массива (шаблон функции) |
|
(C++17) | проверяет, пуст ли контейнер (шаблон функции) |
|
(C++17) | получает указатель на базовый массив (шаблон функции) |
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение согласно опубликованной версии | Корректное поведение |
|---|---|---|---|
| CWG 1181 | C++98 | типы массивов не могли быть типами значений | могут |
| LWG 208 | C++98 | итераторы за концом всегда были несингулярными | могут быть сингулярными |
| LWG 278 | C++98 | корректность итератора не была определена | определено, что он всегда несингулярный |
| LWG 324 | C++98 | выходные итераторы имели типы значений | вместо этого выходные итераторы имеют записываемые типы |
| LWG 407 | C++98 | сингулярные итераторы нельзя было уничтожать | разрешено |
|
LWG 408 (N3066) | C++98 | сингулярные итераторы нельзя было копировать | разрешено, если они инициализированы значением |
|
LWG 1185 (N3066) | C++98 |
LegacyForwardIterator, LegacyBidirectionalIterator и LegacyRandomAccessIterator всегда удовлетворяли требованиям LegacyOutputIterator | они могут не удовлетворять требованиям LegacyOutputIterator |
|
LWG 1210 (N3066) | C++98 | определение сингулярности и достижимости итераторов зависело от контейнеров | вместо этого зависит от последовательностей |
| LWG 3009 | C++17 |
<string_view> не предоставлялшаблоны функций доступа к диапазонам | предоставляет эти шаблоны |
| LWG 3987 | C++23 |
<flat_map> и <flat_set> непредоставляли шаблоны функций доступа к диапазонам | предоставляют эти шаблоны |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator