Пространства имён
Варианты
Действия

Библиотека итераторов

Материал из cppreference.com
< cpp
 
 
Библиотека итераторов
Концепты итераторов
Примитивы итераторов
Концепты алгоритмов и утилиты
Косвенно вызываемые концепты
Общие требования к алгоритмам
Утилиты
(C++20)
Адаптеры итераторов
Потоковые итераторы
Точки настройки итераторов
Операции итераторов
Доступ к диапазону
(C++11)(C++14)
(C++11)(C++14)
(C++17)(C++20)
(C++14)(C++14)
(C++14)(C++14)
(C++17)
(C++17)
 

Итераторы являются обобщением указателей, которые позволяют программе на C++ работать с различными структурами данных (например, с контейнерами и диапазонами(начиная с C++20)) единым образом. Библиотека итераторов предоставляет определения для итераторов, а также свойства итераторов, адаптеры и служебные функции.

Поскольку итераторы являются абстракцией указателей, их семантика является обобщением большей части семантики указателей в C++. Это гарантирует, что каждый шаблон функции, принимающий итераторы, будет работать и с обычными указателями.

Содержание

[править]Категории итераторов

Существует пять(до C++17)шесть(начиная с C++17) видов итераторов: LegacyInputIterator, LegacyOutputIterator, LegacyForwardIterator, LegacyBidirectionalIterator, LegacyRandomAccessIterator и LegacyContiguousIterator(начиная с C++17). (Смотрите также LegacyIterator , где описан самый базовый тип итератора.)

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

Все категории итераторов (кроме LegacyOutputIterator) могут быть организованы в иерархию, где более мощные категории итераторов (например, LegacyRandomAccessIterator) поддерживают операции менее мощных категорий (например, LegacyInputIterator). Если итератор попадает в одну из этих категорий и также соответствует требованиям LegacyOutputIterator, то он называется изменяемым итератором и поддерживает ввод и вывод. Неизменяемые итераторы называются константными итераторами.

Итераторы называются constexpr итераторами если все операции, предусмотренные для соответствия требованиям категории итераторов, являются no section name.

(начиная с C++20)
Категоря итератора Требования к эксплуатации и хранению
     запись           чтение      инкремент  декремент     произвольный   
доступ
 непрерывное 
хранилище
без
   нескольких   
проходов
с
   несколькими   
проходами
LegacyIteratorТребует
LegacyOutputIteratorТребует Требует
LegacyInputIterator
(mutable, если поддерживает операцию записи)
Требует Требует
LegacyForwardIterator
(также соответствует LegacyInputIterator)
Требует Требует Требует
LegacyBidirectionalIterator
(также соответствует LegacyForwardIterator)
Требует Требует Требует Требует
LegacyRandomAccessIterator
(также соответствует LegacyBidirectionalIterator)
Требует Требует Требует Требует Требует
   LegacyContiguousIterator[1]
(также соответствует LegacyRandomAccessIterator)
Требует Требует Требует Требует Требует Требует
  1. LegacyContiguousIterator была только формально определена в C++17, но итераторы std::vector, std::basic_string, std::array и std::valarray, а также указатели на массивы C часто рассматриваются как отдельная категория в коде до C++17.

Примечание: категория 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.

(начиная с C++11)

Для каждого типа итератора Xдля которого определено равенство(до C++20), существует соответствующий знаковый целочисленный(до C++20)целочисленно-подобный(начиная с C++20) тип, называемый разностным типом итератора.

[править]Разыменовываемость и валидность

Точно так же, как обычный указатель на массив гарантирует наличие значения указателя, указывающего на элемент за последним элементом массива, так и для любого типа итератора существует значение итератора, указывающее на элемент за последним элементом соответствующего контейнера(до C++11)последовательности(начиная с C++11). Такое значение называется значением за концом.

Значения итератора i, для которых определено выражение *i называются разыменовываемыми. Стандартная библиотека никогда не предполагает, что значения за конечным значением могут быть разыменованы.

Итераторы также могут иметь единственные значения, не связанные ни с каким контейнером(до C++11)последовательностью(начиная с C++11). Результаты большинства выражений не определены для единственных значений; с единственными исключениями

  • присваивание неединственного значения итератору, который содержит единственное значение,
  • уничтожение итератора, который содержит единственное значение, и,
(начиная с C++11)

В этих случаях единственное значение перезаписывается так же, как и любое другое значение. Разыменовываемые значения всегда не единственные.

Недопустимый итератор это итератор, который может быть единственным.

[править]Диапазоны

Большинство алгоритмических шаблонов стандартной библиотеки, работающих со структурами данных, имеют интерфейсы, использующие диапазоны.

Итератор j называется достижимым из итератора i тогда и только тогда, когда существует конечная последовательность применений выражения ++i, которая делает i == j. Если j достижим из i, они ссылаются на элементы одной и той же последовательности.

Диапазон это пара итераторов, обозначающих начало и конец вычисления. Диапазон [ii) является пустым диапазоном; в общем случае диапазон [ij) ссылается на элементы в структуре данных, начиная с элемента, на который указывает i, и до, но не включая элемент, на который указывает j.

Диапазон [ij) является действительным тогда и только тогда, когда j достижим из i.

(до C++20)

Диапазон это либо

  • сравнимый диапазон[is), итератор i и ограничительs обозначающие начало и конец вычисления (i и s могут иметь разные типы), или
  • подсчитываемый диапазонi + [0, n), итератор i и счетчик n, обозначающие начало и количество элементов, к которым применяются вычисления.
Сравнимый диапазон

Итератор и ограничитель, обозначающий диапазон, сравнимы. [is) пусто, если i == s; иначе, [is) ссылается на элементы в структуре данных, начиная с элемента, на который указывает i, и до, но не включая элемент, если таковой имеется, на который указывает первый итератор j такой, что j == s.

Ограничитель s называется достижимым из итератора i тогда и только тогда, когда существует конечная последовательность применений выражения ++i, которая делает i == s.

Если s достижимо из i, [is) обозначает действительный диапазон.

Подсчитываемый диапазон

Подсчитываемый диапазонi + [0n) пуст, если n ==0; иначе, i + [0n) ссылается на элементы n в структуре данных, начиная с элемента, на который указывает i, и до, но не включая элемент, если таковой имеется, на который указывает результат n применения ++i.

Подсчитываемый диапазон i + [0n) является действительным тогда и только тогда, когда

  • n ==0; или
  • выполняются все следующие условия:
    • n положительно,
    • i разыменовывается, и
    • ++i + [0--n) является действительным.
(начиная с C++20)

Результат применения функций стандартной библиотеки к недопустимым диапазонам не определён.

[править]Концепты итераторов

В C++20 представлена новая система итераторов, основанная на концептах, которая отличается от итераторов C++17. Хотя основная схема остаётся схожей, требования к отдельным категориям итераторов несколько отличаются.

Определены в пространстве имён std
указывает, что тип доступен для чтения косвенно с помощью оператора *
(концепт)[править]
указывает, что значение может быть записано в объект, на который указывает ссылка итератора
(концепт)[править]
указывает, что тип semiregular может увеличиваться с помощью операторов до и после инкремента
(концепт)[править]
указывает, что операция инкремента для типа weakly_incrementableсохраняет равенство и что этот тип является equality_comparable
(концепт)[править]
указывает, что объекты типа могут быть инкрементированы и разыменованы
(концепт)[править]
указывает, что тип является ограничителем для типа input_or_output_iterator
(концепт)[править]
указывает, что оператор - может быть применён к итератору и ограничителю, чтобы вычислить их разницу за постоянное время
(концепт)[править]
указывает, что тип является итератором ввода, то есть значения, на которые он ссылается, могут быть прочитаны, и он может быть как пре-инкрементирован, так и пост-инкрементирован
(концепт)[править]
указывает, что тип является итератором вывода для данного типа значения, то есть в него могут быть записаны значения этого типа, и он может быть как пре-, так и пост-инкрементирован
(концепт)[править]
указывает, что input_iterator является прямым итератором, поддерживающим сравнение на равенство и многопроходность
(концепт)[править]
указывает, что forward_iterator является двунаправленным итератором, поддерживающим движение назад
(концепт)[править]
указывает, что bidirectional_iterator это итератор с произвольным доступом, поддерживающий продвижение за постоянное время и индексирование
(концепт)[править]
указывает, что random_access_iterator является непрерывным итератором, ссылающимся на смежные элементы памяти
(концепт)[править]

[править]Типы, связанные с итераторами

Определены в пространстве имён std
вычисляет разностный тип типа weakly_incrementable
(шаблон класса)[править]
вычисляет тип значения типа indirectly_readable
(шаблон класса)[править]
вычисляет связанные типы итератора
(псевдоним шаблона)[править]

[править]Примитивы итераторов

предоставляет единый интерфейс к свойствам итератора
(шаблон класса)[править]
пустые типы классов, используемые для обозначения категорий итераторов
(класс)[править]
(устарело в C++17)
базовый класс для упрощения определения требуемых типов для простых итераторов
(шаблон класса)[править]

[править]Точки настройки итераторов

Определены в пространстве имён std::ranges
(C++20)
приводит результат разыменования объекта к связанному с ним типу правосторонней ссылки
(объект точки настройки)[править]
(C++20)
меняет местами значения, на которые ссылаются два разыменовываемых объекта
(объект точки настройки)[править]

[править]Концепты алгоритмов и утилиты

C++20 также предоставляет набор концептов и связанных шаблонов служебных утилит, предназначенных для упрощения ограничения операций общих алгоритмов.

Определены в заголовочном файле <iterator>
Определены в пространстве имён std
Косвенно вызываемые концепты
указывает, что вызываемый тип может быть вызван в результате разыменования типа indirectly_readable
(концепт)[править]
указывает, что вызываемый тип, когда он вызывается с результатом разыменования типа indirectly_readable, соответствует predicate
(концепт)[править]
указывает, что вызываемый тип, когда он вызывается с результатом разыменования двух типов indirectly_readable, соответствует predicate
(концепт)[править]
указывает, что вызываемый тип при вызове в результате разыменования двух типов indirectly_readable, соответствует equivalence_relation
(концепт)[править]
указывает, что вызываемый тип, когда он вызывается с результатом разыменования двух типов indirectly_readable, соответствует strict_weak_order
(концепт)[править]
Общие требования к алгоритмам
указывает, что значения могут быть перемещены из типа indirectly_readable в тип indirectly_writable
(концепт)[править]
указывает, что значения могут быть перемещены из типа indirectly_readable в тип indirectly_writable и что перемещение может быть выполнено через промежуточный объект
(концепт)[править]
указывает, что значения могут быть скопированы из типа indirectly_readable в тип indirectly_writable
(концепт)[править]
указывает, что значения могут быть скопированы из типа indirectly_readable в тип indirectly_writable что копирование может быть выполнено через промежуточный объект
(концепт)[править]
указывает, что значения, на которые ссылаются два типа indirectly_readable, можно поменять местами
(концепт)[править]
указывает, что значения, на которые ссылаются два типа indirectly_readable, могут сравниваться
(концепт)[править]
(C++20)
определяет общие требования к алгоритмам, которые меняют порядок элементов на месте
(концепт)[править]
(C++20)
определяет требования к алгоритмам, которые объединяют отсортированные последовательности в выходную последовательность путём копирования элементов
(концепт)[править]
(C++20)
определяет общие требования алгоритмов, которые переставляют последовательности в упорядоченные последовательности
(концепт)[править]
Утилиты
вычисляет результат вызова вызываемого объекта на результате разыменования некоторого набора типов indirectly_readable
(псевдоним шаблона)[править]
(C++20)
вспомогательный шаблон для определения ограничений для алгоритмов, принимающих прогнозы
(шаблон класса)[править]

[править]Адаптеры итераторов

адаптер итератора для обхода в обратном порядке
(шаблон класса)[править]
создаёт std::reverse_iterator типа, выведенного из аргумента
(шаблон функции)[править]
адаптер итератора для вставки в конец контейнера
(шаблон класса)[править]
создаёт std::back_insert_iterator типа, выведенного из аргумента
(шаблон функции)[править]
адаптер итератора для вставки в начало контейнера
(шаблон класса)[править]
создаёт std::front_insert_iterator типа, выведенного из аргумента
(шаблон функции)[править]
адаптер итератора для вставки в контейнер
(шаблон класса)[править]
создаёт std::insert_iterator типа, выведенного из аргумента
(шаблон функции)[править]
адаптер итератора, который преобразует итератор в константный итератор
(шаблон класса)[править]
вычисляет константный тип итератора для заданного типа
(псевдоним шаблона)[править]
вычисляет тип ограничителя, который будет использоваться с константными итераторами
(псевдоним шаблона)[править]
создаёт std::const_iterator типа, полученного из аргумента
(шаблон функции)[править]
создаёт std::const_sentinel типа, выведенного из аргумента
(шаблон функции)[править]
адаптер итератора, который разыменовывается в правостороннюю ссылку
(шаблон класса)[править]
адаптер ограничитель для использования с std::move_iterator
(шаблон класса)[править]
создаёт std::move_iterator типа, выведенного из аргумента
(шаблон функции)[править]
адаптирует тип итератора и его ограничителя к общему типу итератора
(шаблон класса)[править]
ограничитель по умолчанию для использования с итераторами, которые знают границу своего диапазона
(класс)[править]
адаптер итератора, отслеживающий расстояние до конца диапазона
(шаблон класса)[править]
ограничитель, который всегда сравнивает на неравенство с любым типом weakly_incrementable
(класс)[править]

[править]Потоковые итераторы

итератор ввода, читающий из std::basic_istream
(шаблон класса)[править]
итератор вывода, записывающий в std::basic_ostream
(шаблон класса)[править]
итератор ввода, читающий из std::basic_streambuf
(шаблон класса)[править]
итератор вывода, записывающий в std::basic_streambuf
(шаблон класса)[править]

[править]Операции над итераторами

Определены в заголовочном файле <iterator>
продвигает итератор на заданное расстояние
(функция)[править]
возвращает расстояние между двумя итераторами
(функция)[править]
(C++11)
инкрементирует итератор
(функция)[править]
(C++11)
декрементирует итератор
(функция)[править]
продвигает итератор на заданное расстояние или до заданной границы
(ниблоид)[править]
возвращает расстояние между итератором и ограничителем или между началом и концом диапазона
(ниблоид)[править]
инкрементирует итератор на заданное расстояние или до границы
(ниблоид)[править]
декрементирует итератор на заданное расстояние или до границы
(ниблоид)[править]

[править]Доступ к диапазону

Эти функции, не являющиеся элементами, предоставляют общий интерфейс для контейнеров, простых массивов и std::initializer_list.

Определены в заголовочном файле <array>
Определены в заголовочном файле <deque>
Определены в заголовочном файле <forward_list>
Определены в заголовочном файле <iterator>
Определены в заголовочном файле <list>
Определены в заголовочном файле <map>
Определены в заголовочном файле <regex>
Определены в заголовочном файле <set>
Определены в заголовочном файле <span>
Определены в заголовочном файле <string>
Определены в заголовочном файле <string_view>
Определены в заголовочном файле <unordered_map>
Определены в заголовочном файле <unordered_set>
Определены в заголовочном файле <vector>
Определены в пространстве имён std
(C++11)(C++14)
возвращает итератор на начало контейнера или массива
(шаблон функции)[править]
(C++11)(C++14)
возвращает итератор на конец контейнера или массива
(шаблон функции)[править]
возвращает обратный итератор на начало контейнера или массива
(шаблон функции)[править]
(C++14)
возвращает обратный конечный итератор для контейнера или массива
(шаблон функции)[править]
(C++17)(C++20)
возвращает размер контейнера или массива
(шаблон функции)[править]
(C++17)
проверяет, пустой ли контейнер
(шаблон функции)[править]
(C++17)
получает указатель на базовый массив
(шаблон функции)[править]

[править]Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 1181 C++98 типы массивов не могут быть типами значений могут
LWG 208 C++98 итераторы за концом всегда были неособыми они могут быть особыми
LWG 278 C++98 допустимость итератора не была определена определяется как всегда неособый
LWG 324 C++98 выходные итераторы имели типы значений вместо этого выходные итераторы имеют перезаписываемые
типы
LWG 407 C++98 особые итераторы не могли быть уничтожены позволено
LWG 408 C++98 особые итераторы не могли быть скопированы разрешено, если они инициализированы значением
LWG 1185 C++98 LegacyForwardIterator, LegacyBidirectionalIterator
и LegacyRandomAccessIterator всегда
соответствуют LegacyOutputIterator
они могут не соответствовать LegacyOutputIterator
LWG 1210 C++98 определение сингулярности и достижимости
итератора зависело от контейнеров
вместо этого зависит от последовательностей
close