C++迭代器之'反向迭代器'

       反向迭代器(Reverse Iterator)是普通迭代器的适配器,通过重新定义自增和自减操作,以达到按反序遍历元素的目的。如果在标准算法库中用反向迭代器来代替普通的迭代器,那么运行结果与正常情况下相反。除此之外,其用法与普通迭代器完全一样,我们不作详细讨论。

       这里主要讨论的是反向迭代器的一个很特殊、也很容易出错的性质,即它的“逻辑位置”与“物理位置”。先通过看一个例子开始:

vector<int> vec;
for(vector<int>::size_type i=1; i<10; ++i)
{
	vec.push_back(i);
}

vector<int>::iterator itr = vec.begin()+4;
cout<<*itr<<endl;
vector<int>::reverse_iterator r_itr(itr);
cout<<*r_itr<<endl;

这个例子中,vec中存放从1到9的9个连续数字,并初始化一个普通迭代器指向数字5,打印输出结果显而易见,为5。然后再初始化一个反向迭代器,该迭代器指向与普通迭代器一样的物理位置,然后打印输出,这时结果为多少呢?

       如果你不了解反向迭代器这个特殊的性质的话,很容易误认为结果一样是5。但实际情况不是这样,而是4,即前一个位置处的元素!具体原因,即涉及到反向迭代器的“物理位置”与“逻辑位置”两个概念。

       我们都知道,一个容器的范围用普通迭代器表示为一个“半开半闭”的区间。头部为begin,指向容器第一个元素的位置。末尾为end,指向最后一个元素的下一个位置,每个容器都提供了这样一个位置,尽管该位置不可引用,但却是个合法的地址。相反,第一个元素位置的前一个位置容器却没有任何保证,比如对于vector和string来说,就是非法的位置。这里我们说“合法”与“非法”,简单来讲,可以这样认为,一个合法的位置对于迭代器来说是可以达到的,像最后一个元素的下一个位置end()。而对于首元素的前一个位置,迭代器是无法指向它的,begin()-1这个表达式会导致异常。因此,反向迭代器与普通迭代器在物理位置上保持了一一对应,即rbegin()对应普通迭代器的end()位置,rend()对应其begin()位置。

       但是,为了让反向迭代器与普通迭代器在概念上保持一致性,即begin()(反向迭代器对应为rbegin())对应第一个元素(对于反向迭代器来说,最后一个元素即第一个元素),end()(反向迭代器对应为rend())对应最后一个元素的下一个位置,于是标准库的设计者们想出这样一个方法,即反向迭代器的逻辑位置等于其物理位置的前一个位置。换句话说,物理位置对应迭代器在内存中的实际位置,逻辑位置对应迭代器对应容器中元素的位置。这样,对于rbegin()来说,它物理位置是容器最后一个元素的下一个位置,逻辑位置即容器最后一个元素的位置(对反向迭代器来说就是第一个元素元素的位置),同理rend()物理位置为容器第一个元素位置,逻辑位置即第一个位置的前一个位置(依然不可解引用)。这样,反向迭代器与普通迭代器便有了一致的概念,即“半开半闭”区间。更为直观的演示如下图:

 

       (该图片来自:《The C++ Standard Library, A Tutorial And Reference》)

        这样,开头那个例子就很容易解释了,反向迭代器被初始化为与前一个普通迭代器一样的物理位置(对应元素5),其逻辑位置即前一个位置,因些通过解引用得到元素4.

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值