我们知道STL两个主要内容就是容器(containers)和算法(algoritms),两者是分开设计的。关于各自独立的实现,c++中的class template和function template能很好的完成这个目标。而将两者胶合起来,则需要iterator的帮助。这就使得iterator成了STL设计中重要的一环。
迭代器是一种抽象的设计概念,《设计模式》中提供的23种设计模式中的一种。以下是对于其适用性的描述:
1.访问一个聚合对象的内容而无需暴露它的内部表示
2.支持对聚合对象的多种遍历
3.为遍历不同的聚合结构提供一个统一接口
根据《设计模式》中的观点,创建迭代器的参与者可以包含以下几个:
Iterator(迭代器)
迭代器定义和访问的接口
ConcreteIterator(具体迭代器)
具体实现迭代器接口,不同的类有不同的迭代实现 跟踪遍历位置
Aggregate(聚类)
定义和创建相应迭代器对象的接口
ConcreteAggregate(具体聚类)
具体聚合实现创建相应迭代器的接口
所以创建iterator又是一种Factor Method模式,这样做就实现了聚类与迭代机制的分离。当然,STL中的iterator并不完全按这个分层的机制实现。但是,总体上按这个模式来的,对所有的iterator有一个统一的抽象,其中定义了基本的内部类型,和基本的通用的函数操作,而对不同的容器,实现专属迭代器。
迭代器作为访问容器的一个工具,根据访问权限和移动特性可已将其分为以下几类:
Input iterator
单向(operator ++),只读对象,不允许外界改变
Output iterator
单向(operator ++),只写
Forward iterator
单向(operator ++),能写能读
Bidirectional iterator
双向(operator ++/--),能写能读
Random Access iterator
双向(operator ++/--),能写能读,支持随机访问(operator +/- n)
之所以要区别这几种迭代器因为不同的迭代器,某些操作的执行效率会不一样。
STL还在bits\stl_iterator_base_funcs.h中定义了iterator的一些基本操作,主要包括以下几个:
函数声明:difference_type distance(InputIterator first,InputIterator last);
作用: 求两个迭代器的距离
函数声明:void advance(InputIterator& i, Distance n);
作用: 将迭代器i移动n个位置,n可以是负数(双向迭代器)
以下是c++11后增加的两个函数(参考MinGW g++4.8.1)
函数声明:ForwardIterator next(ForwardIterator __x, difference_type __n = 1);
作用:将迭代器x后移一位,并返回x。
函数声明:BidirectionalIterator prev(_BidirectionalIterator __x,difference_type __n = 1);
作用:将双向迭代器x前移一位,并返回x。
上面的几个声明是简化的形式,具体实现时还需要修改。
应该包括哪些操作?应该把哪些操作交给容器?抽象到什么程度?考虑清楚这些问题,直接关系到后面的容器该的怎么设计。在比较了SGI STL和GNU gcc的迭代器设计之后,我决定采用gcc STL的的设计。gcc STL的设计中,container都有自己的iterator,所以一般以[container]::[iterator]的形式访问容器的iterator。这并不是说iterator都直接设计在container里面,虽然不同的容器需要不同的迭代器,但是我们可以对迭代器某些通用的属性和操作进行抽象。所以,迭代器是无法完全从容器中抽离出来单独设计,迭代器的设计主要包括通用抽象部分和具体容器部分。下面以gcc STL的vector的迭代器为例分析迭代器的实现:
TL的vector的迭代器为例分析迭代器的实现:通用的部分:
在bits\stl_iterator_base_type.h和bits\stl_iterator_base_funcs.h中,包含了
所有迭代器相关的类型(如iterator,iterator_traits),函数(如advance,distance)
适配器:
在bits\stl_iterator.h中基于前面的iterater,实现了一些iterator适配器,比如
__normal_iterator,reverse_iterator等。
容器部分:
在bits\stl_vector.h中,使用__normal_iterator<pointer,Container>建立了一个
vector专属的迭代器。
大致上,迭代器的设计包括以上的部分。但是也有特例,比如std::list的迭代器是在内部完全重新写过的。
经过各方面的考量和取舍,我将通用部分合在iterator_base.h
中,将适配器写在stl_iterator.h
中,主要实现_normal_iterator
,其他的放到adapter部分。而容器部分就放到以后实现容器的时候再说。
//my_iterator_base.h #ifndef MY_ITERATOR_H_INCLUDED #define MY_ITERATOR_H_INCLUDED #include<iostream> #include<typeinfo> //for typeid using std::cout; using std::endl; namespace juine { //5个迭代器类型 struct input_iterator_tag{}; struct output_iterator_tag{}; struct forward_iterator_tag:public input_iterator_tag,public output_iterator_tag{}; struct bidirectional_iterator_tag:public forward_iterator_tag{}; struct random_access_iterator_tag:public bidirectional_iterator_tag{}; template<class T> class Iterator_base { public: //作为迭代器所必需的元素(萃取5元素) typedef T value_type; typedef T* pointer; typedef T& reference; typedef size_t difference_type; //iterator_category 需要根据迭代器的类别来判断 //构造函数和析构函数 Iterator_base(T* p=0):point(p){} //copy构造函数怎么写: Iterator_base(const Iterator_base& t):point(t.point){} ~Iterator_base(){delete point;} //实现*和->的引用,++ value_type& operator*(){ return *point; } pointer operator->(){ return point; } Iterator_base operator++() { point++; return *this; } Iterator_base operator++(int) { Iterator_base tmp(*this); ++*this; return tmp; } bool operator!=(Iterator_base iter) { if(point==iter.point) return true; return false; } private: T* point; }; //萃取出迭代器中的各个性质 template<class T> struct strait { //不能写成其他的 ,因为要和标准的STL实现无缝链接 typedef typename T::value_type value_type; typedef typename T::reference reference; typedef typename T::difference_type difference_type; typedef typename T::pointer pointer; typedef typename T::iterator_category iterator_category; }; //偏特化 template<class T> struct strait<T*> { typedef T value_type; typedef T& reference; typedef T* pointer; typedef size_t difference_type; typedef random_access_iterator_tag iterator_category; }; template<class T> struct strait<const T*> { typedef T value_type; typedef T& reference; typedef T* pointer; typedef size_t difference_type; typedef random_access_iterator_tag iterator_category; }; //迭代器常见操作方法之advance方法 template<class InputIterator> void __advance(InputIterator& iter,size_t n,input_iterator_tag ) { while(n--) iter++; cout<<"调用的是InputIterator迭代器"<<endl; } template<class InputIterator> void __advance(InputIterator& iter,size_t n,forward_iterator_tag ) { __advance(iter,n,InputIterator()); cout<<"调用的是ForwardIterator迭代器"; } template<class InputIterator> void __advance(InputIterator& iter,size_t n,bidirectional_iterator_tag ) { if(n>0) while(n-->0) iter++; else while(n++>=0) iter--; cout<<"调用的是BidirectionalIterator迭代器"<<endl; } template<class InputIterator> void __advance(InputIterator& iter,size_t n,random_access_iterator_tag ) { iter+=n; cout<<"调用的是RandomIterator迭代器"<<endl; } //对外统一的接口 template<class InputIterator> void my_advance(InputIterator& iter,size_t n) { cout<<"自制advance"<<endl; typedef typename strait<InputIterator>::iterator_category iterator_category; __advance(iter,n,iterator_category()); } //迭代器常见操作方法之distance方法 template<class InputIterator> typename strait<InputIterator>::difference_type __distance(InputIterator iter1,InputIterator iter2,input_iterator_tag) { typedef typename strait<InputIterator>::difference_type difference_type; difference_type length=0; while(iter1!=iter2) { iter1++; length++; } return length; } template<class InputIterator> typename strait<InputIterator>::difference_type __distance(InputIterator iter1,InputIterator iter2,forward_iterator_tag) { return __distance(iter1,iter2,input_iterator_tag()); } template<class InputIterator> typename strait<InputIterator>::difference_type __distance(InputIterator iter1,InputIterator iter2,random_access_iterator_tag) { typedef typename strait<InputIterator>::difference_type difference_type; difference_type length=iter2-iter1; return length; } //对外实现统一的接口 template<class InputIterator> typename strait<InputIterator>::difference_type my_distance(InputIterator iter1,InputIterator &iter2) { typedef typename strait<InputIterator>::iterator_category iterator_category; typedef typename strait<InputIterator>::difference_type difference_type; difference_type length=__distance(iter1,iter2,iterator_category()); return length; } } #endif // MY_ITERATOR_H_INCLUDED测试代码
//test_iterator.cpp #include<vector> #include<iostream> #include"my_iterator_base.h" using namespace juine; using namespace std; int main() { int a[5]={1,2,3,4,5}; vector<int> vec(a,a+5); vector<int>::iterator iter=vec.begin(); my_advance(iter,2); cout<<"my_advence调用后:"<<*iter<<endl; vector<int>::iterator iter2=vec.begin()+4; cout<<"distance距离为:"<<my_distance(iter,iter2); return 0; }测试结果截图:
从结果可以看出,该迭代器实现了对STL的无缝链接,基本上达到我们预期的结果!
原文:http://blog.csdn.net/bb2b2bbb/article/details/23169891