反向迭代器(Reverse Iterator)是一种反向遍历容器的迭代器。
比如,vector类中有一个名为rbegin()的成员函数和一个名为rend()的成员函数。rbegin()返回一个指向超尾的反向迭代器,rend()返回指向第一个元素的反向迭代器。
正因为它是反向迭代器,所以将自增(和自减)的含义反过来了:对于反向迭代器,++运算将导致它被递减,--运算将导致它被递增。我们来看一下它的源码(stl_iterator.h):
//prefix ++
reverse_iterator&
operator++() {
--current;
return *this;
}
//postfix ++
reverse_iterator
operator++(int) {
reverse_iterator __tmp = *this;
--current;
return __tmp;
}
//prefix --
reverse_iterator&
operator--() {
++current;
return *this;
}
//postfix --
reverse_iterator
operator--(int) {
reverse_iterator __tmp = *this;
++current;
return __tmp;
}
那么第一个问题来了,为什么不直接对常规迭代器进行递减呢?主要的原因是为了简化对已有的函数的使用。
比如copy()函数可以将数据从一个容器复制到另外一个容器中。这种算法是以迭代器方式实现的。
比如:
int casts[10] = {6, 7, 2, 4, 1, 9, 5, 8, 0, 3};
vector<int> dice(10);
copy(casts, casts+10, dice.begin()); //copy array to vector
copy()的前两个迭代器参数表示要复制的范围,即源地址的范围。最后一个迭代器参数表示目的地址的起始位置。copy()函数将覆盖目标容器中已有的数据,同时
目标容器必须足够大,以便能够容纳被复制的元素。
现在,假如想把vector容器dice中的10个元素再逆序写回casts数组中,如果有了反向迭代器,那么我们就还可以使用copy()来完成这项工作。
copy(dice.rbegin(), dice.rend(), casts);
看到这里,我们肯定会有一个很大的疑问:rbegin()返回的是超尾,因此我们不能对该地址进行解引用操作,同时,rend()返回的是第一个元素的位置,这会导致提前一个元素就结束了。是的,所有认真思考的人第一次都会有这样的疑问。为解决刚刚提到的这两个问题,反向迭代器做出了一种特殊的补偿机制,请看它的解引用重载函数:
reference
operator*() const {
_Iterator __tmp = current;
return *--__tmp;
}
反向指针通过先递减,再解引用来解决这两个问题。同时,从上面的代码可以看出,通过解引用操作符,虽然返回的是前一个元素的值,但是, 当前迭代器的值并没有改变。理解这一点很重要。
Done!