我们在编码时,经常用到容器,我们也知道容器的种类很多,例如:数组、链表、集合、树、图等等。这些不同的容器由于内部实现原理的不同,会存在不同的遍历方式。
我们就想,是否能够忽略容器内部结构的不同,提供一种统一的访问操作?当然可以,迭代器能够帮我们实现这一点。另外,需要提到一点,STL 中的容器都提供了迭代器的访问方式,例如:
#include <vector> #include <iostream> #include <set> int main() { // 线性结构 std::vector<int> v = { 10, 20, 30 }; // 树结构 std::set<int> s = { 10, 20, 30 }; // 通过迭代器方式访问 for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) { std::cout << *it << " "; } for (std::set<int>::iterator it = s.begin(); it != s.end(); ++it) { std::cout << *it << " "; } return 0; }
为容器设计迭代器有什么好处呢?可以看如下代码:
#include <vector> #include <iostream> #include <set> template<class T> void print_container(const T &container) { for (typename T::const_iterator it = container.cbegin(); it != container.cend(); ++it) { std::cout << *it << " "; } std::cout << std::endl; } int main() { // 线性结构 std::vector<int> v = { 10, 20, 30 }; // 树结构 std::set<int> s = { 10, 20, 30 }; print_container(v); print_container(s); return 0; }
vector 是线性结构的容器,而 set 是树结构的容器,两者内部结构不同,通过迭代器提供了相同的访问方式,我们不必再关心其内部的结构。当我们编写一个用于所有容器的打印函数时,就可以轻松实现了,如 print_container 函数的实现。
从另外一个角度来看,迭代器帮助我们将业务函数 print_contaier 和容器解耦。需要注意的是,迭代器给我们暴露的操作方式是一样的,但是迭代器在不同容器内部的工作方式是不一样的。所以,每个容器都会自行提供符合内部结构要求的迭代器,这些不同容器的迭代器仅仅是操作方式相同而已。
迭代器模式的使用已经非常广泛了,在几乎所有的编程语言中,都提供了迭代器用于容器遍历访问。