本文作者:campos 本文出处:http://www.mykernelspace.com (转载请保留此行,谢谢)
这次分析的是bits/stl_iterator.h。这个文件其实只是定义了一些iterator的adaptor,也就是进一步的包装了一下iterator这种类型。reverse_iterator, back_insert_iterator, front_insert_iterator, insert_iterator, __normal_iterator是这个文件中定义的几种iterator。他们的基本作用是:给定一个已有的iterator,将这个iterator的行为做一下修改(实际上是复制一个iterator,然后重新定义几个基本的operator)。
reverse_iterator顾名思义就是将原有iterator的操作方向反过来(当然原来的iterator必须是bidirectional或者random_access的)。下面就是这个adaptor类的定义:
template<typename _Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<_Iterator>::iterator_category,
typename iterator_traits<_Iterator>::value_type,
typename iterator_traits<_Iterator>::difference_type,
typename iterator_traits<_Iterator>::pointer,
typename iterator_traits<_Iterator>::reference>
{
// 这个类的模板参数是一个iterator的类型,然后这个iterator的几个基本特征作为它父类iterator的模板参数。iterator_traits的用处在这里体现了出来,它轻松的提取了这个类型的基本特征。而iterator的作用就是把提取出来的基本特征存储下来。
// 这个protected的成员就是原有iterator的拷贝。这是一个基本的Object Adaptor Pattern(相对于Class Adaptor Pattern)。
protected:
_Iterator current;
// 把原有的iterator的类型特征作为reverse_iterator的类型特征,原有的iterator的类型赋给别名iterator_type
public:
typedef _Iterator iterator_type;
typedef typename iterator_traits<_Iterator>::difference_type
difference_type;
typedef typename iterator_traits<_Iterator>::reference reference;
typedef typename iterator_traits<_Iterator>::pointer pointer;
public:
//默认的构造函数,如果_Iterator是指针类型,那么执行的将是一个空初始化
reverse_iterator() : current() { }
//参数为原有iterator的构造函数
explicit reverse_iterator(iterator_type __x) : current(__x) { }
//拷贝构造函数,实际上就是复制两个对象的current成员变量
reverse_iterator(const reverse_iterator& __x) : current(__x.current) { }
// 从其他类型的reverse_iterator拷贝的拷贝构造函数,因为current是reverse_iterator的protected的对象,所以提供了一个base函数返回这个值
template<typename _Iter>
reverse_iterator(const reverse_iterator<_Iter>& __x)
: current(__x.base()) { }
// 返回current(current本身是protected)
iterator_type base() const
{ return current; }
//dereference操作符,因为reverse_iterator一开始是指向最后一个元素后面一个位置的,所以*操作符需要返回当前位置前面一个元素(很可能一开始current是一个container的rbegin())。reverse_iterator返回这个位置前面一个位置的值
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
}
//成员操作符,利用dereference操作符实现
pointer
operator->() const
{ return &(operator*()); }
// 前缀增量操作符,返回current移动后的对象引用
reverse_iterator&
operator++()
{
--current;
return *this;
}
// 后缀增量操作符,返回一个current没有修改过的对象的拷贝
reverse_iterator
operator++(int)
{
reverse_iterator __tmp = *this;
--current;
return __tmp;
}
// 前缀减量操作符
reverse_iterator&
operator--()
{
++current;
return *this;
}
// 后缀减量操作符
reverse_iterator operator--(int)
{
reverse_iterator __tmp = *this;
++current;
return __tmp;
}
// +操作符,返回一个current减去n步的reverse_iterator的拷贝(这里current需要有 “-” 操作符的重载实现)
reverse_iterator
operator+(difference_type __n) const
{ return reverse_iterator(current - __n); }
// +=操作符,返回当前对象的引用
reverse_iterator&
operator+=(difference_type __n)
{
current -= __n;
return *this;
}
// -操作符,返回一个拷贝(最可能的原因是防止作为lvalue)。同+操作符一样,current需要有”+”操作符的重载实现
reverse_iterator
operator-(difference_type __n) const
{ return reverse_iterator(current + __n); }
// -=操作符,返回当前对象的引用
reverse_iterator&
operator-=(difference_type __n)
{
current += __n;
return *this;
}
// 下标操作符。下标的index表示本reverse_iterator“前进” index步,然后返回dereference以后的值
reference
operator[](difference_type __n) const
{ return *(*this + __n); }
};
随后,文件中定义了8个两个reverse_iterator之间比较的模板函数,这里不一一分析了,举一个例子足够:
template<typename _Iterator>
inline bool
operator==(const reverse_iterator<_Iterator>& __x,
const reverse_iterator<_Iterator>& __y)
{ return __x.base() == __y.base(); }
这个内联函数重载了相等操作符,参数是两个具有相同underlying iterator类型的reverse_iterator对象。真正的实现是通过比较两个reverse_iterator的base函数返回的current的值来实现的。所以这个实现依赖于_Iterator类型的==操作符。8个函数当中最后一个也值得提及一下:
template<typename _Iterator>
inline reverse_iterator<_Iterator>
operator+(typename reverse_iterator<_Iterator>::difference_type __n,
const reverse_iterator<_Iterator>& __x)
{ return reverse_iterator<_Iterator>(__x.base() - __n); }
这个函数也是实现了加法操作符,但是跟reverse_iterator的成员函数operator+不一样。成员函数只负责 (reverse_iterator+n) 的情况,但是(n+reverse_iterator)的情况没有cover。这个函数只是使实现更为全面。
接下来看看另外一个Adaptor模板--back_insert_iterator。这个模板和前面的reverse_iterator不一样,这个模板的参数不是另外一个iterator,而是一个container。而这个container是必须符合一定要求的。这个要求就是”back_insert”,简单来说就是支持push_back函数的容器,比如说deque、list和vector。下面就是这个模板类的定义:
//可以看出,这个Adaptor以一个容器类型作为模板参数,同时它也是output_iterator类型的,也就是只能写,不能读
template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
//保存这个容器的指针
protected:
_Container* container;
// 定义_Container类型为container_type,方便引用
public:
typedef _Container container_type;
// 唯一的一个构造函数,创建这个iterator的唯一方法就是传入一个容器的对象
explicit
back_insert_iterator(_Container& __x) : container(&__x) { }
// 最重要的一个操作符:赋值操作符。给定一个新的容器包含元素的类型的对象,然后利用容器的push_back将这个元素插入到容器的尾部
back_insert_iterator&
operator=(typename _Container::const_reference __value)
{
container->push_back(__value);
return *this;
}
// 因为是一个output_iterator,所以所有读相关的操作都是返回iterator本身(iterator本身没有任何数据)
back_insert_iterator&
operator*()
{ return *this; }
// 同时不支持前缀增量运算符,因为push_back的同时相当于向后移动了
back_insert_iterator&
operator++()
{ return *this; }
// 同理不支持后缀增量运算符
back_insert_iterator
operator++(int)
{ return *this; }
};
这个模板类的问题就是:假如说我要声明一个back_insert_iterator的实例针对list,我需要这样写:
back_insert_iterator<list> it(list_instance);
我有一个list的实例list_instance,但是我还是需要知道这个实例的准确类型list,因为这个iterator只提供了一个构造函数。因此STL的设计者加入了下面这个模板函数back_inserter:
template<typename _Container>
inline back_insert_iterator<_Container>
back_inserter(_Container& __x)
{ return back_insert_iterator<_Container>(__x); }
这个函数只需要一个模板实例作为参数,在调用这个函数的同时,容器的类型也隐式地传给了模板,减轻了用户的负担。这确实是一个“贴心”的设计。
随后的front_insert_iterator这个Adaptor和back_insert_iterator的实现相同,这里就不再鳌述了。之后定义的insert_iterator的实现也大抵相同,就留作家庭作业了:)
最后,这个文件定义了一个__normal_iterator模板类,这个类不在std的namespace中,而是在__gnu_cxx中。这个模板类有两个参数,一个是_Iterator,另外一个是_Container。从代码的注释中可以了解到这个模板类是把不是iterator类但是具有iterator特性的类型(比如说指针)转换为iterator类型;而后面的_Container类型纯粹是作为一个区分的参数,这样不同的_Container就可以生成不同的__normal_iterator模板类的实例。举个简单的例子,比如说我有两个容器,list<int> 和 vector<int>,我可以用 __gnu_cxx::__normal_iterator<int*, std::list<int> > 和 __gnu_cxx::__normal_iterator<int*, std::vector<int> >生成两个iterator,分别对两个容器里面的int指针进行包装。事实上在我们以后要研究的vector容器中,vector::iterator就是用__normal_iterator生成的。
结语:Whewwwww,iterator基本上就能介绍这么多了,也许有机会再介绍一下另外两个包含在<iterator>中的ostream和istream。纵观介绍的三个头文件,可以看出:
- bits/stl_iterator_base_types.h真正定义了iterator,但是没有定义任何真正的操作,因为真正的操作是容器相关的,比如说vector可以用__normal_iterator这个Adaptor来生成iterator,但是list就要考虑到底层的链表结构来实现iterator。bits/stl_iterator_base_types.h最重要的是定义了几种iterator的继承关系,iterator必须的一些类型特征信息,可以说只是定义了iterator的元信息,每个容器的iterator是在每个容器自己的头文件中实现的,包含<iterator>只是提供一些元数据。
- bits/stl_iterator_base_funcs.h定义了advance和distance两个函数,到现在为止没有看到在哪里用(奇怪。。),估计以后研究容器的时候会发现。
- 今天讨论的bits/stl_iterator.h定义几个重要的iterator相关的Adaptor。因为有了这些Adaptor,容器只需要关心实现最基本的iterator,这些变种iterator可以通过这些Adaptor来实现,这是一个典型的高效和高封装性的设计。