目录
前言
一、基本框架
二、起始位置和结束位置
三、反向迭代器的自增与自减
四、反向迭代器的判断
五、list类的修改
六、单独设计反向迭代器类的意义
前言
反向迭代器实际上与我们前面的stack、queue、priority一样,都是适配器;我们可以通过正向迭代器构建出反向迭代器;
一、基本框架
我们首先创建一个反向迭代器的头文件;我们将所有反向迭代器的代码放入这个文件中;
前面我们也说过了,反向迭代器实际上是一种适配器,其实是对任意双向的正向迭代器的封装;因此有了以下代码;
namespace MySpace
{
// Iterator为迭代器模板参数,Ref为数据的引用类型,Ptr为数据的指针类型
template<class Iterator, class Ref, class Ptr>
class __reverse_iterator
{
public:
typedef __reverse_iterator<Iterator, Ref, Ptr> self;
__reverse_iterator(Iterator it)
: _it(it)
{}
private:
Iterator _it;
};
}
二、起始位置和结束位置
首先,我们要确定的是反向迭代器起始位置与结束位置,在list中,我们一般会想着将起始位置定位最后一个数据的位置,而结束位置为哨兵位头节点的位置;而在STL库中,为了追求对称之美,起始位置和结束位置如下图所示;
这样定义的话,对于解引用,又出了一些问题,我们必须要对其--,也就是访问前一个位置的数据;因此,对于*的重载与->的重载,有了如下代码;
Ref operator*() const
{
// 找到前一个位置的数据
Iterator tmp(_it);
--tmp;
// 这里的*是在传入参数的那个迭代器实现的重载(即正向迭代器的*)
return *tmp;
}
Ptr operator->() const
{
Iterator tmp(_it);
--tmp;
// 这里的->是在传入参数的那个迭代器实现的重载(即正向迭代器的->)
return tmp->_data;
}
三、反向迭代器的自增与自减
反向迭代器的自增与自减我们可以分别调用正向迭代器的自减与自增来实现;即他加我减,他减我加;
self& operator++()
{
--_it;
return *this;
}
self operator++(int)
{
self tmp(_it);
--_it;
return tmp;
}
self& operator--()
{
++_it;
return *this;
}
self operator--(int)
{
self tmp(_it);
++_it;
return tmp;
}
四、反向迭代器的判断
对于反向迭代器的判断,我们只需重载==与!=即可;我们也可以调用正向迭代器的==与!=来实现;
bool operator==(const self& rit)
{
return _it == rit._it;
}
bool operator!=(const self& rit)
{
return _it != rit._it;
}
五、list类的修改
前面我们将反向迭代器的类实现了,这里我们还需要在list类中重定义反向迭代器名(统一接口名),以及添加相关接口(如rbegin、rend等)
// 反向迭代器
typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
// 反向迭代器相关成员函数
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
添加了如上代码后,我们的反向迭代器便可以运行了;
六、单独设计反向迭代器类的意义
可以看到,我们单独将反向迭代器放入一个单独的文件,也设计了一个单独的类,这有什么意义呢? 实际上,我们刚才设计的反向迭代器的接口也可以适用于vector等容器,我们仅仅只需要实现vector正向迭代器,我们便可通过这个反向迭代器对正向迭代器进行封装即可,仅仅在类中添加一些接口就可以适配上,因此我们实现的反向迭代器是一种适配器;关于list与vector的反向迭代器的源码,我放在了下面供大家参考;
vector反向迭代器
list反向迭代器