当前位置: 首页 > article >正文

C++:关于反向迭代器的学习分享

前言:

        小编仅是一位初学者,所以对于C++的理解有限,文章大概率会出现表达不清楚可能也只是因为小编不知道如何更好表达,本文章仅作为一个学习的总结分享。

反向迭代器的概念

        反向迭代器故名思意解释反向的迭代器,与正向迭代器相反。正向迭代器的遍历是从前往后进行遍历,那么反向迭代器则是从后往前进行遍历。

        以下是对于反向迭代器的官方解释。

        反向迭代器是一个类模板,这个类反转了双向迭代器随机访问迭代器遍历范围的方向。

        内部保持了原始迭代器(即基迭代器)的一个副本,并用来反映在 reverse_iterator 上执行的操作:每当 reverse_iterator 被递增时,它的基迭代器会被递减,反之亦然。可以随时通过调用成员函数 base 获得具有当前状态的基迭代器的副本。

        可以看到反向迭代器的类模板参数是一个正向迭代器,那么就说明,只要容器支持正向迭代器就可以通过传入的正向迭代器取复用反向迭代器。那么这么做的好处就是并不需要每个支持正向迭代器的容器都要自己去写一份反向迭代器,而是直接复用反向迭代器的类模板,让编译器自身去实例化出相应的反向迭代器。

        随机访问迭代器:

                随机访问迭代器就是支持迭代器的+,-,++,--以及operator[ ]的操作,支持随机访问迭代器的容器有vector,string。他们的特点为是地址都是连续的一片地址空间。

        双向迭代器:

                双向迭代器就是仅支持迭代器的++,--操作,不支持+,-以及operator[ ],如list。因为list并不是一段连续的地址空间。

         那么在使用反向迭代器的时候会发现反向迭代器是通过++,来访问上一个容器的数据。

        反向迭代器的begin位置对应容器的end位置,反向迭代器的end位置对应容器的begin位置,为了方便理解,下图是一个list的begin位置以及end位置,那么相对于的就是list的反向迭代器的rbegin位置以及rend位置。

 

反向迭代器的实现

        为了方便理解,小编简单实现了一个反向迭代器。

	template<class Iterator ,class Ref ,class Ptr>
	struct Reverse_iterator
	{
		Iterator _it;
		Reverse_iterator(const Iterator& it)
			:_it(it)
		{}

		typedef Reverse_iterator<Iterator,Ref, Ptr> self;

		
		Ref operator*()
		{
			Iterator temp = _it;
			return *(--temp);
		}

		Ptr operator ->()
		{
			return &(_it.operator*());
		}

		self& operator++()
		{
			 --_it;
			 return *this;
		}

		self& operator--()
		{
			--_it;
			return *this;
		}

		bool operator!=(const self&it) const
		{
			return _it != it._it;
		}

	};

        小编的反向迭代器的类模板参数有三个:1.Iterator,2.Ref,3.Ptr。看过上期小编文章可以知道,Ref就是对模板参数T类型的引用,Pter就是模板参数T类型的指针。

        反向迭代器里只有一个成员变量,这个成员变量就是一个正向迭代器的对象。那么反向迭代器的初始化其实就是通过传入的正向迭代器的参数对反向迭代器里的it进行初始化。

        

        函数 Ref operator*()其实就==T&operator*(),访问的是容器里的数据。

        函数里的操作是创建一个新的正向迭代器值,并把_it赋值给temp。接着先--temp,在解引用temp。那么这里是经历了什么操作呢?

        不要忘记,反向迭代器其实是对容器的正向迭代器进行的再一次封装,必定是先有正向迭代器才会有反向迭代器。所以这里--temp操作会去调用正向迭代器的operator--。如果正向迭代器里没有那么就会报错。

        下图我将拿上期文章实现的list来举例。

        先对反向迭代器进行typedef,接着创建list的rbgin与rend函数,可以看到rbegin与rend都是去调用正向迭代器的begin与end。

        通过上图就说明了为什么函数 Ref operator*( )中,为什么temp需要先--在解引用。temp迭代器的--会调用正向迭代器的operator--,而*temp则会调用正向迭代器的operator*( )。

        

        那么反向迭代器的operator++()与 operator--()函数会调用正向迭代器的operator--()与operator++(),并且内部都是对正向迭代器的函数复用操作。唯一特殊的就是解引用。      

        

反向迭代器的好处是什么

        反向迭代器允许从容器的末尾向开头遍历元素。这对于一些算法或操作是非常方便的。

        1.逆序输出:你可能想要从容器的最后一个元素开始打印,反向迭代器使得这一过程非常简单如list的逆序打印,相对比起C语言,简单不要太多。

        2.从后向前的查找:在某些情况下,查找可能从容器的末尾开始是更高效的。

        3.因为反向迭代器是一个类模板,所以可以兼容任何有正向迭代器的容器。

                        

                                                             ————那么本片文章就到这里,感谢各位观众老爷观看。


http://www.kler.cn/a/289643.html

相关文章:

  • 计算机毕业设计必看必学35755flask旅游景区热度可视化平台原创定制程序,java、PHP、python、小程序、文案全套、毕设成品等
  • Android 下内联汇编,Android Studio 汇编开发
  • Ai创作新风标!仅需三步,利用ai工具免费制作抖音爆款的动物融合视频(含完整的步骤)
  • Cesium加载大量点数据卡顿处理办法
  • 使用 Vue 配合豆包MarsCode 实现“小恐龙酷跑“小游戏
  • ubuntu20.04安装anaconda与基本使用
  • 缓存类型以及读写策略
  • RocketMQ高级特性三-消费者分类
  • java 常用并发队列- ArrayBlockingQueue
  • malab 将数据导入到excell文件代码的几种方法
  • LeetCode hot100刷题记录
  • LACP链路聚合
  • Android 9.0 SystemUI状态栏/快捷设置介绍
  • 【网络原理】Udp 的报文结构,保姆式教学,快速入门
  • 计算机网络 第2章 物理层
  • 多个Node.js版本之间切换
  • css spacing设置间距
  • redis缓存和数据库通过延迟双删除实现数据一致性
  • Ghidra逆向工具之旅与二进制代码分析【4】
  • 通过设置JVM参数来启用GC(垃圾回收)日志
  • Super Image 2.1.0 图像处理软件,修复老照片、无损放大、智能修复,本地处理保护隐私
  • 如何选择SSD
  • java实现ocr功能(Tesseract OCR)
  • 数据库中LIKE 和 NOT LIKE的用法辨析
  • 嵌入式学习(数据结构:链表)
  • Apache Storm:入门了解