大家好,我是小贺。
1. 前言
天下大事,必作于细。
源码之前,了无秘密。
上一篇,我们剖析了 STL 空间配置器,这一篇文章,我们来学习下 STL 迭代器以及背后的 traits 编程技法。
在 STL 编程中,容器和算法是独立设计的,容器里面存的是数据,而算法则是提供了对数据的操作,在算法操作数据的过程中,要用到迭代器,迭代器可以看做是容器和算法中间的桥梁。

2. 迭代器设计模式
为何说迭代器的时候,还谈到了设计模式?这个迭代器和设计模式又有什么关系呢?
其实,在《设计模式:可复用面向对象软件的基础》(GOF)这本经典书中,谈到了 23 种设计模式,其中就有 iterator 迭代模式,且篇幅颇大。
碰巧,笔者在研究 STL 源码的时候,同样的发现有 iterator 迭代器,而且还占据了一章的篇幅。
在设计模式中,关于 iterator 的描述如下:一种能够顺序访问容器中每个元素的方法,使用该方法不能暴露容器内部的表达方式。而类型萃取技术就是为了要解决和 iterator 有关的问题的。
有了上面这个基础,我们就知道了迭代器本身也是一种设计模式,其设计思想值得我们仔细体会。
那么 C++ STL 实现 iterator 和 GOF 介绍的迭代器实现方法什么区别呢? 那首先我们需要了解 C++ 中的两个编程范式的概念,OOP(面向对象编程)和 GP(泛型编程)。
在 C++ 语言里面,我们可用以下方式来简单区分一下 OOP 和 GP

在 STL 编程结构里面,迭代器其实也是一种模板 class
,迭代器在 STL 中得到了广泛的应用,通过迭代器,容器和算法可以有机的绑定在一起,只要对算法给予不同的迭代器,比如 vector::iterator、list::iterator,std::find()
就能对不同的容器进行查找,而无需针对某个容器来设计多个版本。
这样看来,迭代器似乎依附在容器之下,那么,有没有独立而适用于所有容器的泛化的迭代器呢?这个问题先留着,在后面我们会看到,在 STL 编程结构里面,它是如何把迭代器运用的炉火纯青。
3. 智能指针
STL 是泛型编程思想的产物,是以泛型编程为指导而产生的。具体来说,STL 中的迭代器将范型算法 (find, count, find_if)
等应用于某个容器中,给算法提供一个访问容器元素的工具,iterator
就扮演着这个重要的角色。
稍微看过 STL 迭代器源码的,就明白迭代器其实也是一种智能指针,因此,它也就拥有了一般指针的所有特点—— 能够对其进行 *
和 ->
操作。
template<typename T>
class ListIterator {//mylist迭代器
public:
ListIterator(T *p = 0) : m_ptr(p){} //构造函数
T& operator*() const { return *m_ptr;} //取值,即dereference
T* operator->() const { return m_ptr;} //成员访问,即member access
//...
};
但是在遍历容器的时候,不可避免的要对遍历的容器内部有所了解,所以,干脆把迭代器的开发工作交给容器的设计者,如此以来,所有实现细节反而得以封装起来不被使用者看到,这也正是为什么每一种 STL 容器都提供有专属迭代器的缘故。
比如笔者自己实现的