在设计容器时,避免不了的就是设计与之契合的迭代器。迭代器,行为类似指针,担任访问元素、提领元素的重任。为什么说是重任呢?因为访问、提领虽是简单易实现的操作,但也是使用频率最高的两个操作。使用频率高,即意味着任何对性能有着极大的影响,所以我们要对迭代器的类别进行细致的划分,力求将每一种迭代器的性能都发挥到极限。(例如vector的迭代器为原生指针,原生指针可以实现随机存取(Random Access Iterator)。如果我们像是用笨拙的(相对来说)双向迭代器(Bidrectional Iterator)的一样,用++、--在相邻元素间移动,就太委屈他所拥有的能力了。)
我们首先对迭代器根据移动特性与操作方式(读、写),将其分为五类:
Input Iterator(输入迭代器):这种迭代器所指的对象,不允许外界改变。只能对其进行读操作。
Output Iterator(输出迭代器):这种迭代器所指的对象,只能对其进行写操作。
Forward Iterator( 可读可写迭代器):这种迭代器所指的对象,可以读取,也可以写入。
Bidrectional Iterator(双向迭代器):这种迭代器支持双向遍历,即支持++(递增),--(递减)操作,同时支持以上三种迭代器的操作。
Random Access Iterator(随机迭代器):这种迭代器支持跳跃式的对象处理能力,体现于支持[](根据索引值锁定目标),同时也支持以上所有迭代器的操作。
以上迭代器的能力具有层层扩展的关系,如何实现这种包含关系呢?最简单的方法就是继承:
struct stl_input_iterator_tag{};//输入迭代器
struct stl_output_iterator_tag{};//输出迭代器
struct stl_forward_iterator_tag :public stl_input_iterator_tag{};//可读写迭代器
struct stl_bidirectional_iterator_tag :public stl_forward_iterator_tag{};//双向迭代器
struct stl_random_access_iterator_tag :public stl_bidirectional_iterator_tag{};//随机迭代器
如同type_traits(型别萃取),我们设立这几个类的目的是过后为其设置类型别名,以帮助我们区分迭代器。(这几个类别皆为全局变量)
那我们如何在迭代器上烙上迭代器类别的印记呢?
一种方法就是使用类型别名:
template
class vector_Iterator
{
public:
typedef stl_random_access_iterator_tag iterator_category;
...
protected:
T* itor;
};
但对于每一个迭代器的实现都如此实现会涌现大量重复代码。为了避免重复,我们单独设置一个类别,专门定义迭代器相关的各种型别,再使迭代器类继承于它:
//型别集装箱,迭代器皆继承此类
template
struct iterator
{
typedef Category iterator_category;//迭代器类型
typedef T value_type;//迭代器所指对象类型
typedef Distance difference_type;//迭代器之间距离类型
typedef Pointer pointer;//迭代器所指对象的指针型别
typedef Reference reference;//迭代器所指对象的引用型别
};
我们再设立一个迭代器萃取装置:
//型别萃取器,类型型别由迭代器自主更改
template//模板参数应设为迭代器
struct stl_iterator_traits
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::Distance difference_type;
typedef typename Iterator::Pointer pointer;
typedef typename Iterator::Reference reference;
};
//copy算法的内层实现
template
struct _copy_dispatch
{
OutputIterator operator()(InputIterator first,InputIterator last,OutputIterator result)
{
typedef typename stl_iterator_traits::iterator_category iterator_category;
return _copy(first,last,result,iterator_category());
}
};
//特例化原生指针类型
template
struct stl_iterator_traits
{
typedef stl_random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef ptrdiff_t diference_type;
typedef T& reference;
};
template
struct stl_iterator_traits
{
typedef stl_random_access_iterator_tag iterator_category;
typedef T value_type;
typedef const T* pointer;
typedef ptrdiff_t diference_type;
typedef const T& reference;
};