所有类型的迭代器都必须有一个拷贝构造函数、一个析构函数以及一个拷贝赋值运算符。
迭代器指向的对象必须是可交换的(swappable)。
C++ 提供了 5 种类型的迭代器,各迭代器之前的继承关系如下:
Input <---+
+ <--- Forward <--- Bidirectional <--- Random access
Output <---+
不同的迭代器分别反映了它们不同层次的功能。不同的算法要求具有不同功能的迭代器,以此来确认算法能做哪些操作。
类型 | 输出/Out | 输出/In | 前向/For | 双向/Bi | 随机访问/Ran |
---|---|---|---|---|---|
读 | =*p | =*p | =*p | =*p | |
访问 | -> | -> | -> | -> [] | |
写 | *p= | *p= | *p= | *p= | |
迭代 | ++ | ++ | ++ | ++ -- | ++ -- + - += -= |
比较 | == != | == != | == != | == != < > <= >= |
C++ 中通过称作迭代器标签类的空类来指定 5 种不同的迭代器:
语法
struct output_iterator_tag{};
空类,用于标识迭代器为输出迭代器。
说明
- 输出迭代器用于相继输出的操作,每个被输出迭代器指向的元素只会写一次,之后输出迭代器自增。
- 所有的前向、双向和随机访问的非常量迭代器都是输出迭代器。
语法
struct input_iterator_tag{};
空类,用于标识迭代器为输入迭代器。
说明
- 输入迭代器用于相继输入的操作,每个被输入迭代器指向的元素只会读一次,之后输入迭代器自增。
- 所有的前向、双向和随机访问的迭代器都是输出迭代器。
语法
struct forward_iterator_tag{};
空类,用于标识迭代器为前向迭代器。
说明
- 前向迭代器只允许从开头开始访问一个序列范围内的元素。
语法
struct bidirectional_iterator_tag{};
空类,用于标识迭代器为双向迭代器。
说明
- 双向迭代器可以从双向(开头或结尾)开始访问一个序列范围内的元素。
- 所有的随机访问迭代器(random-access iterators)都是双向迭代器。
- 双向迭代器具有前向迭代器(forward iterators)的特性,但同时它还具备自减(--)特性。
- 所有的双向迭代器也是前向迭代器和输入迭代器。
语法
struct random_access_iterator_tag{};
空类,用于标识迭代器为随机访问迭代器。
说明
- 随机访问迭代器可以以相对它们指向位置的任意偏移值访问元素,类似于指针功能。
- 所有的指针类型也是随机访问迭代器。
因为是迭代器标签类是个空类,所以它只是个标识。也就是说假如你在实现迭代器时,如果将迭代器声明为 bidirectional_iterator_tag, 但却定义了 += 操作符,也没关系。这全靠自觉。