文章目录
- 1. list的反向迭代器
- 2. list的rbegin和rend
- 3. 反向迭代器的实现
- 3.1 复用vector反向迭代器
- 3.2 反向迭代器的变化
1. list的反向迭代器
我们先来看一看库里面的list的迭代器是如何写的:
这是list的正向迭代器。
这是list的反向迭代器。
其实大佬们是把正向迭代器封装适配了一下,生成了反向迭代器。
原因是:和正向迭代器相比,除了++/- -方向相反,其它操作基本一致。
那么我们就来看一下库里面的写法:
从上面就可以看出,它通过一个正向迭代器的成员变量来完成反向迭代器的工作。在下面我们要注意以下两点:
反向迭代器的解引用是正向迭代器前一个位置,箭头也是如此
反向迭代器的++是正向迭代器的- -,- -是正向迭代器++
2. list的rbegin和rend
我们先来看一下库里面是如何设计的:
它的rbegin就是end,rend就是begin。
这种设计也叫做对称设计。当我们执行下面代码时。
rit=rbegin();
while(rit!=rend())
{
*rit;
++rit;
}
所以当解引用时,它是解引用前一个位置的数据。++时其实是正向迭代器的- -,- -就是正向迭代器的++。
3. 反向迭代器的实现
我们先按照正向迭代器那样,自己去写一下:
还是和正向迭代器一样,我们要进行返回。因为要传const和非const两种,我们需要在模板参数多添加两种:
因为这个模板类型,我们可以typedef一下,方便以后使用。
然后我们将一些函数也写一下:
然后我们要在list类里面把rbegin和rend写出来:
我们来测试一下:
这样其实没什么问题。那么const修饰的我们也写一下:
在这里要注意:把const的放在上面写,不然定义的reverse_iterator会影响。
3.1 复用vector反向迭代器
vector和list也是一样的:
然后我们来测试一下:
我们看到没有问题。所以当我们写好一份反向迭代器时,就可以复用到其它容器里,不需要重复写了。
3.2 反向迭代器的变化
可能有的同学会在这里问:库里面写的反向迭代器只有一个模板类型,为什么这里我们写了三个。原因是:库里面早期也是这样实现的,但是后面加了一些修改:
其实一个参数时,最大的问题是它们两个返回值的问题。我们需要这样做:
其实在每个迭代器里面都会有这些定义。然后会这样写:
我们去这个迭代器类域里找这两个。但是这里还有一点问题:没有实例化之前不能去它里面找内嵌定义的类型。因为类模板没有实例化,找出来也是虚拟类型,编译器不认识,后期无法处理。
我们可以这样:
这个typename意思就是:告诉编译器后面这一串是一个类型,等Iterator实例化以后,在去它里面找这个内嵌类型。
我们可以看到list这样写也是没有问题的,但是这种写法vector不行。
因为vector的迭代器是一个原生指针,它没有内嵌类型。list可以是因为它的迭代器是自定义类型,里面可以去设置。那么解决的办法就是:
自己把这个原生指针里包装一下,然后在里面去设置reference和pointer的一些东西。其实标准库里没有使用这种方法,而是一种叫做迭代器萃取的技术来完成的,但是这个技术太复杂了,就不说了。