Namespaces
Variants

Iterator library

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(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函数 ,则称该迭代器为 constexpr 迭代器。

(C++20 起)
迭代器类别 操作与存储要求
写入 读取 递增操作 递减操作 随机访问
连续存储
不保证
多次遍历
支持
多次遍历
LegacyIterator 必需
LegacyOutputIterator 必需 必需
LegacyInputIterator
(若支持写入操作则为可变迭代器)
必需 必需
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 之前的代码中通常被视为单独的类别。

注意:支持上表某一行所需操作的类型不一定属于对应类别,完整要求请参阅类别页面。

定义

类型与可写性

输入迭代器 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 起) 操作的源。

在这些情况下,奇异值的覆写方式与其他值相同。可解引用的值始终是非奇异的。

一个 无效 迭代器是可能为奇异值的迭代器。

Ranges

标准库中大多数操作数据结构的算法模板都使用范围作为接口。

若存在有限次应用表达式 ++ i 能使 i == j ,则称迭代器 j 可从迭代器 i 抵达 。若 j 可从 i 抵达,则它们指向同一序列中的元素。

范围 是指定计算起始与结束的一对迭代器。范围 [ i , i ) 为空范围;通常而言,范围 [ i , j ) 表示数据结构中从 i 指向的元素开始,到 j 指向的元素(不包含该元素)为止的所有元素。

当且仅当 j 可从 i 抵达时,范围 [ i , j ) 有效的

(C++20 前)

范围 可通过以下任一方式表示:

  • [ i , s ) ,使用迭代器 i 哨位 s 指定计算的起始与结束( i s 可具有不同类型);或
  • i + [ 0 , n ) ,使用迭代器 i 与计数 n 指定计算的起始位置及要应用计算的元素数量。
迭代器-哨位范围

表示范围的迭代器与哨位需可比较。若 i == s ,则 [ i , s ) 为空范围;否则, [ i , s ) 表示数据结构中从 i 指向的元素开始,到首个满足 j == s 的迭代器 j 指向的元素(若存在)为止(不包含该元素)的所有元素。

若存在有限次应用表达式 ++ i 能使 i == s ,则称哨位 s 可从迭代器 i 抵达

s 可从 i 抵达,则 [ i , s ) 表示一个 有效的 范围。

计数范围

n == 0 ,则 计数范围 i + [ 0 , n ) 为空范围;否则, i + [ 0 , n ) 表示数据结构中从 i 指向的元素开始,连续 n 个元素(不包含第 n 次应用 ++ i 后指向的元素)的集合。

当且仅当满足以下条件时,计数范围 i + [ 0 , n ) 有效的

  • n == 0 ;或
  • 以下所有条件均成立:
    • n 为正数,
    • i 可解引用,且
    • ++ i + [ 0 , -- n ) 是有效的。
(C++20 起)

标准库函数应用于无效范围的结果是未定义的。

迭代器概念 (始于 C++20)

一套基于 concepts 的新迭代器体系,该体系与C++17迭代器有所不同。虽然基本分类结构保持相似,但各迭代器类别的要求存在一定差异。

定义于命名空间 std
指定类型可通过应用 * 运算符间接读取
(概念)
指定值可写入迭代器所引用的对象
(概念)
指定 semiregular 类型可通过前置和后置递增运算符进行递增
(概念)
指定对 weakly_incrementable 类型的递增操作是 保等式的 且该类型是 equality_comparable
(概念)
指定类型行为类似(有符号)整数类型
( 仅用于说明的概念* )
指定类型的对象可被递增和解引用
(概念)
指定类型是 input_or_output_iterator 类型的哨兵
(概念)
指定可对迭代器和哨兵应用 - 运算符以在常数时间内计算它们的差值
(概念)
指定类型是输入迭代器,即可读取其引用值且支持前置和后置递增
(概念)
指定类型是给定值类型的输出迭代器,即可向其写入该类型的值且支持前置和后置递增
(概念)
指定 input_iterator 是前向迭代器,支持等式比较和多趟遍历
(概念)
指定 forward_iterator 是双向迭代器,支持向后移动
(概念)
指定 bidirectional_iterator 是随机访问迭代器,支持常数时间前进和下标访问
(概念)
指定 random_access_iterator 是连续迭代器,引用内存中连续的元素
(概念)

迭代器关联类型 (自 C++20 起)

定义于命名空间 std
计算 weakly_incrementable 类型的差值类型
(类模板)
计算 indirectly_readable 类型的值类型
(类模板)
计算迭代器的关联类型
(别名模板)

迭代器原语

为迭代器属性提供统一接口
(类模板)
用于指示迭代器类别的空类类型
(类)
(C++17 中已弃用)
用于简化简单迭代器必需类型定义的基类
(类模板)

迭代器定制点 (since C++20)

定义于 命名空间 std::ranges
(C++20)
将对对象解引用的结果转换为其关联的右值引用类型
(定制点对象)
(C++20)
交换两个可解引用对象所引用的值
(定制点对象)

算法概念与工具 (since 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)
用于指定接受投影的算法约束的辅助模板
(别名模板)
通过投影计算 indirectly_readable 类型的值类型
(别名模板)

迭代器适配器

用于反向遍历的迭代器适配器
(类模板)
根据参数类型推断创建 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)
递减迭代器
(函数模板)
使迭代器前进给定距离或到达指定边界
(算法函数对象)
返回迭代器与哨位间的距离,或范围起始与结束间的距离
(算法函数对象)
按给定距离或边界递增迭代器
(算法函数对象)
按给定距离或边界递减迭代器
(算法函数对象)

范围访问 (since C++11)

这些非成员函数模板为容器、普通数组和 std::initializer_list 提供了通用接口。

定义于头文件 <array>
定义于头文件 <deque>
定义于头文件 <flat_map>
定义于头文件 <flat_set>
定义于头文件 <forward_list>
定义于头文件 <inplace_vector>
定义于头文件 <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
( 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>
提供范围访问函数模板
提供这些模板