【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍

这篇具有很好参考价值的文章主要介绍了【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

前言

本篇主要讲反向迭代器的模拟实现。

能够加深各位对泛型的理解。

前面我那篇string介绍里面已经提到过反向迭代器是啥了,如果点进来的同学还不知道,可以看看:[string介绍](https://blog.csdn.net/m0_62782700/article/details/130796914?
spm=1001.2014.3001.5501)

迭代器,可以在不暴露底层实现细节的情况下,提供统一的方式去访问容器。
那么其屏蔽了底层实现,体现除了C++的封装的价值。

这些专业术语,就不说那么多了,下面说人话。

正式开始

前面两篇栈和队列与优先级队列,这三个都是容器适配器,就是传什么容器,就能够用什么容器来实现其函数接口。

如果对于适配器不清楚,可以看我这两篇:
【C++】STL栈和队列基本功能介绍、题目练习和模拟实现(容器适配器)
【C++】STL优先级队列(priority_queue)功能介绍以及模拟实现

那么这一篇讲的是反向迭代器,其也是适配器,但是不是容器适配器,而是迭代器适配器,对照着上面容器适配器的话来说,就是当我们传入什么容器的正向迭代器,就生成对应的容器的反向迭代器。

是不是有点懵了,先别懵,咱们实现起来就搞清楚了。

基本演示

其实反向迭代器和正向迭代器差别是不大的。

我们先用vector演示一下正向和反向迭代器:

正向
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

反向
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

用起来就是名字上差了点区别而已。

模拟实现的大致思路

前面我那篇list模拟实现的最后也说到了,要模拟实现反向迭代器,需要在栈和队列这块学了适配器才能真正领悟到其精髓,不然吃不透。那么现在适配器已经学了,既可以说一说反向迭代器了。

对于我们普通人来说,如果我们想要实现一个反向迭代器,会怎么做?
我当时是这样想的,对于list而言,迭代器是其结点的地址,那么我可以在各个反向迭代器的接口中复用一下list迭代器的正向接口。

大致的图解是这样的:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
那么如果是这样写的话,我们就可以用这样的思路来搞一搞。

但是库中的可不是这样实现的,库可是大佬写出来的。
大佬是怎么想的呢?

  1. list的反向迭代器搞出了,vector的反向迭代器怎么搞?
  2. 如何复用正向迭代器?
  3. 是否可以搞出来迭代器适配器?

那么我们就来根据大佬的思路搞一搞。

首先就是适配器的问题,就是第一点和第三点。
当我们传入什么容器的正向迭代器,就生成对应的容器的反向迭代器。
那么就要搞一个模板参数Iterator,这个模板参数用来接收传入的迭代器。

然后就是复用的问题。
我们就复用传入的正向迭代器,来实现我们的反向迭代器。

那么就先搭出框架。

基本框架

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
上面就复用了传入的迭代器,生成一个__reverse_iterator的成员变量_cur,但是其本质还是iterator的。这就是复用。

那么构造函数我们就要用一个Iterator的变量来给_cur赋值。
就长这样:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
然后我们再复用Iterator的++、–、*、->等函数来实现反向的迭代器。
在这之前我们可以先把我们的当前类重命名一下,写着方便点。

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

这就是用正向的来实现反向的,不是传存储的数据类型T,而是传正向的迭代器。
因为我们定义对象的时候是直接用容器后面跟着<数据类型>,比如说list就是list<int>,数据类型T在这里就定好了。
所以其反向的迭代器就是list<int>::reverse_iterator,并不是在迭代器的后面定类型的。
而这里用迭代器定义对象的时候,也不用在reverse_iterator后面加上<Iterator>,因为我们定义list<int>的时候是先在list类内typedef正向的迭代器的,正向迭代器的模板参数就是<T, T&, T*>,只要前面T定好了,正向的迭代器就搞好了,之后才轮到我们现在写的反向迭代器的,而反向迭代器模板参数直接穿的是正向迭代器Iterator,所以说只要vector类中模板参数T定好了,那么后面的所有类型就都定好了。是不需要我们手动再传任何的模板参数的。

如果上面这段话看起来非常懵的话,可以看看我前面几篇STL容器的模拟实现。

然后就复用一下正向迭代器的几个函数接口。来实现一下反向迭代器的++、–、*、->等接口。

前置++、–

反向迭代器和正向迭代器是相反的遍历顺序,那么就可以用正向的++来实现反向的–,用正向的–来实现反向的++。
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
后置的我就不写了,各位自己练个手。

*重载

*,就是解引用,返回的值能修改,那么返回引用即可,但是我们这里模板参数没有传数据类型T,不知道怎么搞定这个返回值。那么有两种做法,一个是萃取,非常麻烦,本人能力有限,搞不定。二个就是再写下模板参数即可。
那我当然选第二个了,更轻松一点,但是后面还有->重载,我们加上两个模板参数,一个引用,一个指针。

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
然后记得改内部的那个typedef:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

写一下*重载:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

->重载

我在list实现中,也写过这个:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
看不懂的话,我只能说看一下我的这篇实现:【C++】手把手教你模拟实现list的基本功能

其实不用往下写了。
上面的模拟实现和库中的是不一样的。
为什么呢?
因为我们从图解那里就和库中的不一样。
我们来看一看库中的*和->重载是啥:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
可以看到,*重载返回的是cur - 1。

再来看一下list库中的rbegin和rend:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
不知道各位能看出来啥不?
就是rbegin是end,rend是begin。

那么对应到图解中就是这样的:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
而我们画的图解是这样的:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
所以问题就出现了。

我们就可以把我们的*和->改一改。
其实改*就好。
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
由于我的list模拟里没有实现减法重载,但实现–了,就凑合一下,也能用。

然后再实现以下 !=反向的迭代器就能用了。
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

list和vector适配反向迭代器

我们用list模拟的代码来用一用这里的反向迭代器,在我们的list迭代器中,搞出来反向迭代器和rbegin、rend。记得在list中引用一下我们反向迭代器的头文件。

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

rbegin和rend:

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

然后来测试一下:

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

list实现了,我们也用vector实现一下,同样,也是要在vector头文件中typedef一下反向迭代器并实现rbegin和rend。

代码typedef的代码、rbegin、rend的代码和list一模一样,我就不写了。

测试一下:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
完全是OK的。

那么到这里迭代器适配器就讲完了。
上面用了list和vector的正向迭代器两个例子来适配出了各自的反向迭代器。很成功。

那么问题来了:只要有正向迭代器就能适配出反向迭代器吗?
答案是错误的。要有条件,必须能够支持++和–。但最主要的还是–。

迭代器的类型

我们来看一下所有的容器:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

这里面,只有forward_list、unordered_map、unordered_set的迭代器没有–的函数接口,剩下的都有。但是为什么呢?

因为迭代器也是分类的。
共三类:

  1. forward_iterator(单向迭代器)

只支持++

相关容器有:forward_list、unordered_map、unordered_set

  1. bidirectional_iterator(双向迭代器)

支持++和–

相关容器有:list、map、set

  1. random_access_iterator(随机访问迭代器)

支持++、–还有+和-

相关容器有:vector、deque

上面的相关容器我只给了常用的,一些不常用的没写上去。

这里三个迭代器是有继承关系的,但由于我前面还没有写过关于继承的博客,所以我只能略提一嘴。

但是文档中有一个表概括的非常全面,不过是英文的,这里截出来给大家看一眼:
【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list
不知道各位英文怎么样,如果实在看不懂,我把这个页面的网址给大家:<iterator>。 往下翻一翻就能看到。

上面的表中对应的有不同类型迭代器能够重载的操作符。
比如说+,Random Access可以重载,但是bidirectional和forward就不能。

根据这个关系就可以得出:双向可实现单向,随机也可实现双向和单向。

再来看个东西,库中的sort和reverse。

库中reverse和sort模板参数中的迭代器

reverse

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

sort

【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍,c++,迭代器,反向迭代器,STL,算法,vector,list

上面两个模板参数中其实已经在提示你改用什么样的迭代器了。
sort传容器的迭代器至少是随机访问迭代器,reverse传容器的迭代器至少是双向迭代器。

所以我们链表就不能用算法库中的sort,要自己实现一个,因为链表的迭代器是双向迭代器。

好了,该讲的都讲得差不多了。

到此结束。。。文章来源地址https://www.toymoban.com/news/detail-595902.html

到了这里,关于【C++】STL反向迭代器模拟实现,迭代器适配器,迭代器类型简单介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【c++】:反向迭代器适配器:每天学一点点优秀的思想

        文章目录 前言 一、list的反向迭代器         vector的反向迭代器 总结   反向迭代器的适配只用于双向迭代器,对于单链表实现的单向迭代器是不能通过适配构造一个反向迭代器的,为什么要说反向迭代器适配器呢?因为我们只需要实现一个反向迭代器模板就可以用所有

    2023年04月09日
    浏览(41)
  • 【C++】STL中stack,queue容器适配器的模拟实现(使用deque容器)

    🌏博客主页: 主页 🔖系列专栏: C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 😍期待与大家一起进步! 虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和

    2024年02月15日
    浏览(50)
  • 【C++】STL中的容器适配器 stack queue 和 priority_queue 的模拟实现

    适配器是一种设计模式 (设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。 例如我们常见的充电器就是一种适配器,它将我们常用的220V交流电压转化为4,5V (或者其他更高的电

    2023年04月26日
    浏览(59)
  • 容器适配器---deque和STL ---stack queue priority_queue的模拟实现 C++

    目录 一、容器适配器 deque原理 deque的缺陷 deque的优势 二、stack的模拟实现  三、queue的模拟实现 四、优先级队列的模拟实现 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户

    2024年02月02日
    浏览(52)
  • [C++] STL_priority_queue(优先级队列) 的使用及底层的模拟实现,容器适配器,deque的原理介绍

    priority_queue文档介绍 翻译: 1. 优先队列是一种 容器适配器 ,根据严格的弱排序标准, 它的第一个元素总是它所包含的元素中最大的。 2. 此上下文类似于 堆 , 在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。 3. 优先队列被实现为容器适配

    2024年02月04日
    浏览(40)
  • 面试之快速学习STL-迭代适配器

    参考:http://c.biancheng.net/view/7255.html 例子: 想使用反向迭代器实现逆序遍历容器,则该容器的迭代器类型必须是双向迭代器或者随机访问迭代器。 常见操作 注意这里不能用std::list,因为它是双向迭代器, +3的操作需要随机访问迭代器 。故联想到std::list排序只能使用list提供的

    2024年02月11日
    浏览(42)
  • 【STL】容器适配器stack和queue常见用法及模拟实现

    1.stack介绍及使用 1.1 stack的介绍 stack文档介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 stack是作为容器适配器被实现的,容器适配器是使用特定容器类的封装对象作为其基础容器的类,提供一

    2024年02月06日
    浏览(44)
  • STL容器适配器 -- stack和queue(使用+实现)(C++)

    栈和队列数据结构+画图分析如果对栈和队列的结构不了解的,可以先看该链接的内容 使用stack时需要头文件 #includestack stack是一种容器适配器,用于具有 后进先出 (LIFO)的环境中。只能从容器的一端(栈顶),执行删除、插入和提取操作。 stack是作为容器适配器实现的,容器

    2024年02月14日
    浏览(61)
  • 【C++】STL之适配器---用deque实现栈和队列

    目录 前言 一、deque  1、deque 的原理介绍  2、deque 的底层结构  3、deque 的迭代器  4、deque 的优缺点   4.1、优点   4.2、缺点 二、stack 的介绍和使用  1、stack 的介绍  2、stack 的使用  3、stack 的模拟实现 三、queue 的介绍和使用  1、queue 的介绍   2、queue 的使用  3、queue 的模

    2024年02月07日
    浏览(50)
  • C++ [STL容器适配器]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT 前面我们介绍了适配器模式中的反向迭代器,反向迭代器通过容器所支持的正向迭代器适配为具有反向迭代功能的迭代器,本节我们介绍STL中另一种适配器: 容器适配器 ! 前面我们提到过STL适配器模式,关于适配器的解释: S

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包