-- TOC --
迭代器iterator是C++ STL的组件之一,作用是用来遍历容器container,而且是通用的遍历容器元素的方式,无论容器是基于什么数据结构实现。尽管不同的数据结构,遍历元素的方式不一样,但是用迭代器遍历不同容器的代码可以是完全一样的。
C++提供的range-based loop,就是基于迭代器的实现。
简单来说,迭代器就是重载了++
,--
,*
等操作符的对象,迭代器一般作为容器类型的子类存在。由于STL中的容器都实现了接口风格完全一致的迭代器,因此,通过迭代器遍历容器中对象的代码,也几乎是一样的。
The interface between containers and algorithms is the iterator. An iterator is a type that knows the internal structure of a container and exposes simple, pointerlike operations to a container’s elements.
常用的迭代器按功能强弱分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种。
假设 p 是一个前向迭代器,则 p 支持 ++p,p++,*p 操作,还可以被复制或赋值,可以用 == 和 != 运算符进行比较。此外,两个正向迭代器可以互相赋值。
双向迭代器具有前向迭代器的全部功能,除此之外,假设 p 是一个双向迭代器,则还可以进行 --p 或者 p-- 操作。
随机访问迭代器具有双向迭代器的全部功能。除此之外,假设 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:
p += i:使得 p 往后移动 i 个元素。
p -= i:使得 p 往前移动 i 个元素。
p + i:返回 p 后面第 i 个元素的迭代器。
p - i:返回 p 前面第 i 个元素的迭代器。
p[i]:返回 p 后面第 i 个元素的引用。
此外,两个随机访问迭代器 p1、p2 还可以用 <、>、<=、>= 运算符进行比较。另外,表达式 p2-p1 也是有定义的,其返回值表示 p2 所指向元素和 p1 所指向元素的序号之差(也可以说是 p2 和 p1 之间的元素个数减一)。
另外,cbegin
中的c,表示const,通过const迭代器
,不可以修改对象的内容。
迭代器的实现,不一定是通过指针,C++迭代器更像一个规范。
下面,我来尝试实现自己的第1个学习用迭代器。这段代码实现了依附于fib对象的正向迭代器:
#include <iostream>
using namespace std;
struct fib {
struct fib_iterator {
fib_iterator(void) = default;
bool operator!=(int x) const {
return x >= cur;
}
fib_iterator& operator++() {
const int tmp = cur;
cur += last;
last = tmp;
return *this;
}
int operator*() {
return cur;
}
private:
int cur{1};
int last{1};
};
explicit fib(int max): max{max} {}
fib_iterator begin() const {
return fib_iterator{};
}
int end() const {
return max;
}
private:
int max;
};
int main(void) {
auto f = fib{2000};
// basic for loop
for (auto x{f.begin()}; x!=f.end(); ++x)
cout << *x << " "; // x is iterator
cout << endl;
// range-based for loop
for (auto x: f)
cout << x << " "; // x is int object
cout << endl;
return 0;
}
编译和输出:
$ g++ -Wall -Wextra test.cpp -o test
$ ./test
1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
fib对象的end接口返回max,它的迭代器重载了!=
符号,在循环时与max进行比较,如果达到max了,就返回false,此时循环的判断条件不再满足,循环结束。
因为*
操作符在重载时,返回的是int值,而不是int引用,因此在使用range-based loop的时候,就不能写成auto &x
。
本文链接:https://cs.pynote.net/sf/c/cpp/202211042/
-- EOF --
-- MORE --