【C++11 之rbegin()、rend() 反向迭代器原理介绍及 重点-限制情况】与正向迭代器对比(互换放在下一p)

C++11 引入了许多新特性,其中包括对 STL(Standard Template Library)的改进。在 STL 容器中,rbegin() 和 rend() 是两个新的成员函数,它们分别返回指向容器最后一个元素的反向迭代器(reverse iterator)和指向容器“理论上的前一个元素”的反向迭代器(该迭代器实际上并不指向任何有效元素,而是作为结束标记)。

反向迭代器介绍

反向迭代器是一种特殊的迭代器,它允许我们按照与正向迭代器相反的顺序遍历容器。也就是说,如果我们使用正向迭代器从容器的开始遍历到结束,那么使用反向迭代器就是从容器的结束遍历到开始。

使用场景

反向迭代器在需要逆序遍历容器元素的场景中非常有用。例如,你可能想要从后向前检查一个字符串是否以某个子串结尾,或者你可能想要逆序打印一个向量的所有元素。

与正向迭代器原理对比

正向迭代器和反向迭代器在原理上的主要区别在于它们如何定义“下一个”元素。对于正向迭代器,++it 将迭代器向前移动到下一个元素;而对于反向迭代器,++it 将迭代器向后移动到“上一个”元素。注意,这里的“上一个”和“下一个”是相对于容器的遍历方向而言的。

代码对比

以下是使用正向迭代器和反向迭代器遍历 std::vector 的示例代码:

#include <iostream>  
#include <vector>  
  
int main() {  
    std::vector<int> v = {1, 2, 3, 4, 5};  
  
    // 使用正向迭代器遍历  
    for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {  
        std::cout << *it << ' ';  
    }  
    std::cout << '\n';  
  
    // 使用反向迭代器遍历  
    for (std::vector<int>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit) {  
        std::cout << *rit << ' ';  
    }  
    std::cout << '\n';  
  
    return 0;  
}

在这个示例中,我们首先使用正向迭代器从前往后遍历 vector,然后使用反向迭代器从后往前遍历 vector。输出将是:

1 2 3 4 5   
5 4 3 2 1

注意,虽然正向迭代器和反向迭代器在语法上有所不同(特别是它们的类型),但它们的用法非常相似:都可以使用 * 运算符来解引用迭代器以访问元素,都可以使用 ++ 运算符来移动迭代器,等等。

看完你会发现反向迭代器其实也没有太多特殊的。是的,但反向迭代器本身设置了很多的限制,所以认识反向迭代器,我们一定要熟悉其限制机制;

重点-限制情况

  1. 依赖双向迭代器:
    反向迭代器通常基于容器的双向迭代器实现。因此,如果容器仅支持单向迭代器(如某些输入迭代器),则无法使用反向迭代器。
    这意味着反向迭代器不能用于如 std::istream_iterator 这样的单向迭代器类型。
  2. 特定操作不可用:
    反向迭代器不支持随机访问迭代器的某些操作,如 operator+=、operator+、operator-=、operator- 和 operator[]。这是因为反向迭代器的内部机制并不直接支持这些操作。
    例如,你不能直接通过 rit + 3 来跳过三个元素(其中 rit 是一个反向迭代器),因为这需要知道“理论上的前一个元素”的位置,这在反向迭代器的上下文中是不可知的。
  3. 引用和指针的语义:(这个难以理解就在下一p中熟悉-C++17新特性)
    反向迭代器的 &*rit(取反向迭代器 rit 指向元素的地址)操作与正向迭代器有所不同。在反向迭代器的上下文中,&*rit 实际上引用的是迭代器在原有序列中引用的元素之外(右侧)一个位置的元素。
    这意味着你不能直接通过反向迭代器来获取容器中元素的原始地址(除非你使用额外的逻辑来转换它)。
  4. 迭代器的有效性:
    反向迭代器的有效性同样受到容器修改操作的影响。如果在遍历过程中修改了容器的大小(如添加或删除元素),则可能导致反向迭代器失效。
    需要注意的是,即使正向迭代器在容器修改后仍然有效,其对应的反向迭代器也可能不再有效。
  5. 类型差异:
    反向迭代器的类型与正向迭代器的类型不同。在 C++ 中,你需要使用如 std::vector::reverse_iterator 这样的类型来声明反向迭代器。
    这意味着你不能直接将正向迭代器赋值给反向迭代器,或者期望它们在类型上兼容。
  6. 使用场景限制:
    虽然反向迭代器在处理需要逆序遍历容器的场景时非常有用,但它们并不适用于所有情况。在某些情况下,使用正向迭代器可能更加直观和高效。

归纳来说,反向迭代器的限制主要源于其基于双向迭代器的设计和实现方式,以及与正向迭代器的差异。这些限制在使用反向迭代器时需要特别注意,以避免潜在的问题和错误。

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

another heaven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值