前言
关于反向迭代器,字如其名,就是将正向迭代器,从反方向再迭代一次就成了,所以我们如此设计反向迭代器:
- 假设我们已经拥有了一套能够使用,且包含模板的正向迭代器
- 利用适配器模式,让反向迭代器封装正向迭代器
- 利用模板的设计,让反向迭代器可以适应多种类型
统一使用规范
对于正向迭代器,为了确保各种容器使用时的统一性(名字统一,操作统一),我们常用typedef
来更改名字、用运算符重载
来更改运算规则,达到使用时的统一。而反向迭代器也是如此
例:
正向:typedef __list_iterator<T,T&,T*> iterator;
反向:typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;
这里是自定义实现的list的正向/反向迭代器,由于原生指针不满足所需,所以对原生指针进行了封装,封装成了
__list_iterator
类,给他取名叫iterator。
然后再一步对正向迭代器进行封装,形成了反向迭代器,给他取名叫reverse_iterator。
这个有3个模板参数:template<class Iterator,class Ref,class Ptr>,这3个参数会在后文说明
正向:typedef T* iterator;
反向:typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;
这是定义的vector的正向/反向迭代器,由于其在存储空间上是连续的,所以原生指针就可以满足正向迭代器的需求,所以给T*取名叫iterator。
然后再一步对正向迭代器进行封装,形成了反向迭代器,取名叫reverse_iterator。
…
迭代器的模板参数
template<class iterator,class Ref,class Ptr>
class iterator:
iterator是该反向迭代器封装的正向迭代器的类型,所以理论上该反向迭代器可以适用于任何正向迭代器。
class Ref:
对于反向迭代器内部的某些操作,可能需要返回T&
,所以除了iterator这一模板参数外,还要添加一个引用类型的模板参数Ref(reference)。
class Ptr:
有些操作可能需要返回T*
,所以增加了Ptr这一模板参数
例:这里的reverse_iterator传的参就是对应上面的参数
typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
运算符重载的各种实现
反向迭代器的构造函数
由于反向迭代器只需要封装一个元素:iterator,所以他的成员变量只有一个
Iterator _it;Reverse_iterator(Iterator it):_it(--it){ }
他的构造函数则如上表示,原因如下图
对于反向迭代器,它采用的是
rend()
和rbegin()
,这也是常用的取法
rend():等价于begin()
rbegin():等价于end()
但是由于rbegin()
的位置并不是最后一个元素所在的位置,并且非有效位,所以在初始化构造的时候就需要对正向迭代器进行 - - 操作,使得其指向最后一个有效位
operator++ && operator- -
对于这一对运算符,他们要做的正好和符号相反,++要实现的实际上是正向迭代器的- -,所以实现起来也很简单,反向迭代器的++调用正向迭代器的- -,反向迭代器的–调用正向迭代器的++
self& operator++()//前置++{--_it;return *this;}self operator++(int)//后置++。由于返回值是一个临时变量,所以不能引用返回{self cur = _it;_it--;return cur;}self& operator--(){++_it;return *this;}self operator--(int){self cur = _it;_it++;return cur;}
operator* && operator-> && operator== && operator!=
这些运算符的实现需求都与正向迭代器相同,所以他们只需要调用正向迭代器的对应操作就可以实现
Ref operator*(){return *_it;}bool operator!=(const self& tmp){return _it != tmp._it;}bool operator==(const self& tmp){return _it == tmp._it;}Ptr operator->(){return _it.operator->();//这里的_it的实现是:return &xxx;有取地址符,返回的是一个指针}
operator[]
该运算符对list无用(没有实现 [ ] 重载的情况下),但是对vector、string…有用
其作用就是返回该容器某个位置的引用
Ref operator[](size_t pos){return *(_it + pos);}
这里是对存储空间连续的结构,去找到pos位置的元素,并对其解引用,返回该点的引用。
如果非要实现对存储空间不连续的结构,需要重载其 [ ] ,然后上述重载仍然适用
反向迭代器代码
template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{typedef Reverse_iterator<Iterator, Ref, Ptr> self;Reverse_iterator(Iterator it):_it(--it){ }Iterator _it;Ref operator[](size_t pos){return *(_it + pos);}self& operator++(){--_it;return *this;}self operator++(int){self cur = _it;_it--;return cur;}self& operator--(){++_it;return *this;}self operator--(int){self cur = _it;_it++;return cur;}Ref operator*(){return *_it;}bool operator!=(const self& tmp){return _it != tmp._it;}bool operator==(const self& tmp){return _it == tmp._it;}Ptr operator->(){return _it.operator->();}
};