Iterator library
迭代器是对 指针 的泛化,允许C++程序以统一方式处理不同的数据结构(例如 容器 和 范围 (C++20起) )。迭代器库提供了迭代器的定义,以及迭代器特征、适配器和工具函数。
由于迭代器是指针的抽象化,其语义是对 C++ 中指针语义的泛化。这确保了每个接受迭代器的 函数模板 在使用常规指针时同样有效。
目录 |
迭代器类别
存在 五种 (C++17前) 六种 (C++17起) 迭代器类型: LegacyInputIterator 、 LegacyOutputIterator 、 LegacyForwardIterator 、 LegacyBidirectionalIterator 、 LegacyRandomAccessIterator 以及 LegacyContiguousIterator (C++17起) 。(另请参阅 LegacyIterator 了解最基础的迭代器类型。)
迭代器的每个类别并非由特定类型定义,而是通过可对其执行的操作来定义。这种定义意味着任何支持必要操作的类型都可以用作迭代器——例如,指针支持 LegacyRandomAccessIterator 所需的所有操作,因此指针可以在任何需要 LegacyRandomAccessIterator 的场合使用。
所有迭代器类别(除 LegacyOutputIterator 外)均可按层级结构进行组织,功能更强的迭代器类别(例如 LegacyRandomAccessIterator )支持功能较弱类别(例如 LegacyInputIterator )的操作。若迭代器属于这些类别之一且同时满足 LegacyOutputIterator 的要求,则称其为可变迭代器,同时支持输入和输出操作。非可变迭代器称为常量迭代器。
|
若为满足迭代器类别要求所提供的所有操作均为
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 起) 操作的源。
在这些情况下,奇异值的覆写方式与其他值相同。可解引用的值始终是非奇异的。
一个 无效 迭代器是可能为奇异值的迭代器。
Ranges
标准库中大多数操作数据结构的算法模板都使用范围作为接口。
|
若存在有限次应用表达式 ++ i 能使 i == j ,则称迭代器 j 可从迭代器 i 抵达 。若 j 可从 i 抵达,则它们指向同一序列中的元素。
范围
是指定计算起始与结束的一对迭代器。范围
当且仅当
j
可从
i
抵达时,范围
|
(C++20 前) |
|
范围 可通过以下任一方式表示:
迭代器-哨位范围
表示范围的迭代器与哨位需可比较。若
i
==
s
,则
若存在有限次应用表达式 ++ i 能使 i == s ,则称哨位 s 可从迭代器 i 抵达 。
若
s
可从
i
抵达,则
计数范围
若
n
==
0
,则
计数范围
i
当且仅当满足以下条件时,计数范围
i
|
(C++20 起) |
标准库函数应用于无效范围的结果是未定义的。
迭代器概念 (始于 C++20)
一套基于 concepts 的新迭代器体系,该体系与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++17 中已弃用)
|
用于简化简单迭代器必需类型定义的基类
(类模板) |
迭代器定制点 (since C++20)
|
定义于 命名空间
std::ranges
|
|
|
(C++20)
|
将对对象解引用的结果转换为其关联的右值引用类型
(定制点对象) |
|
(C++20)
|
交换两个可解引用对象所引用的值
(定制点对象) |
算法概念与工具 (since 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)
|
计算用于常量迭代器的哨兵类型
(别名模板) |
|
(C++23)
|
根据参数类型推断创建
std::const_iterator
(函数模板) |
|
(C++23)
|
根据参数类型推断创建
std::const_sentinel
(函数模板) |
|
(C++11)
|
解引用为右值的迭代器适配器
(类模板) |
|
(C++20)
|
用于
std::move_iterator
的哨兵适配器
(类模板) |
|
(C++11)
|
根据参数类型推断创建
std::move_iterator
(函数模板) |
|
(C++20)
|
将迭代器类型及其哨兵适配为通用迭代器类型
(类模板) |
|
(C++20)
|
用于知晓其范围边界的迭代器的默认哨兵
(类) |
|
(C++20)
|
跟踪到范围末尾距离的迭代器适配器
(类模板) |
|
(C++20)
|
始终与任何
weakly_incrementable
类型比较不相等的哨兵
(类) |
流迭代器
|
从
std::basic_istream
读取的输入迭代器
(类模板) |
|
|
向
std::basic_ostream
写入的输出迭代器
(类模板) |
|
|
从
std::basic_streambuf
读取的输入迭代器
(类模板) |
|
|
向
std::basic_streambuf
写入的输出迭代器
(类模板) |
迭代器操作
|
定义于头文件
<iterator>
|
|
|
使迭代器前进给定距离
(函数模板) |
|
|
返回两个迭代器间的距离
(函数模板) |
|
|
(C++11)
|
递增迭代器
(函数模板) |
|
(C++11)
|
递减迭代器
(函数模板) |
|
(C++20)
|
使迭代器前进给定距离或到达指定边界
(算法函数对象) |
|
(C++20)
|
返回迭代器与哨位间的距离,或范围起始与结束间的距离
(算法函数对象) |
|
(C++20)
|
按给定距离或边界递增迭代器
(算法函数对象) |
|
(C++20)
|
按给定距离或边界递减迭代器
(算法函数对象) |
范围访问 (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++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>
未
提供范围访问函数模板 |
提供这些模板 |