关于反向迭代器,字如其名,就是将正向迭代器,从反方向再迭代一次就成了,所以我们如此设计反向迭代器:
对于正向迭代器,为了确保各种容器使用时的统一性(名字统一,操作统一),我们常用typedef
来更改名字、用运算符重载
来更改运算规则,达到使用时的统一。而反向迭代器也是如此
例:
正向:typedef __list_iterator
反向:typedef Reverse_iterator
这里是自定义实现的list的正向/反向迭代器,由于原生指针不满足所需,所以对原生指针进行了封装,封装成了
__list_iterator
类,给他取名叫iterator。
然后再一步对正向迭代器进行封装,形成了反向迭代器,给他取名叫reverse_iterator。
这个有3个模板参数:template,这3个参数会在后文说明
正向:typedef T* iterator;
反向:typedef Reverse_iterator
这是定义的vector的正向/反向迭代器,由于其在存储空间上是连续的,所以原生指针就可以满足正向迭代器的需求,所以给T*取名叫iterator。
然后再一步对正向迭代器进行封装,形成了反向迭代器,取名叫reverse_iterator。
…
template
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()
的位置并不是最后一个元素所在的位置,并且非有效位,所以在初始化构造的时候就需要对正向迭代器进行 - - 操作,使得其指向最后一个有效位
对于这一对运算符,他们要做的正好和符号相反,++要实现的实际上是正向迭代器的- -,所以实现起来也很简单,反向迭代器的++调用正向迭代器的- -,反向迭代器的–调用正向迭代器的++
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->();//这里的_it的实现是:return &xxx;有取地址符,返回的是一个指针
}
该运算符对list无用(没有实现 [ ] 重载的情况下),但是对vector、string…有用
其作用就是返回该容器某个位置的引用
Ref operator[](size_t pos)
{
return *(_it + pos);
}
这里是对存储空间连续的结构,去找到pos位置的元素,并对其解引用,返回该点的引用。
如果非要实现对存储空间不连续的结构,需要重载其 [ ] ,然后上述重载仍然适用
template
struct Reverse_iterator
{
typedef Reverse_iterator 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->();
}
};