【C++】模拟实现reverse_iterator(反向迭代器适配器)

news2024/12/25 9:14:31

🦄个人主页:修修修也

🎏所属专栏:实战项目集

⚙️操作环境:Visual Studio 2022


目录

一.了解项目功能

📌什么是适配器

📌了解reverse_iterator官方标准

📌了解模拟实现reverse_iterator

二.逐步实现项目功能模块及其逻辑详解

📌实现reverse_iterator成员变量

📌实现reverse_iterator()构造函数

📌实现operator++函数重载

📌实现operator++(int)函数重载

📌实现operator--函数重载

📌实现operator--(int)函数重载

📌实现operator*函数重载

📌实现operator->函数重载

📌实现operator!=函数重载

📌实现operator==函数重载

三.项目完整代码

📌ReverseIterator.h文件

结语


一.了解项目功能

📌什么是适配器

        适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口 :


📌了解reverse_iterator官方标准

        在本次项目中我们的目标是模拟实现一个reverse_iterator,先一起看一下C++标准文档中reverse_iterator的定义:cplusplus : C++ reverse_iterator标准文档icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/iterator/reverse_iterator/?kw=reverse_iterator

        反向迭代器示意图:

        如果对正向迭代器的实现还不太了解的朋友可以先移步下面这篇文章的第三部分,文章以List迭代器为例,手把手教大家如何构建迭代器类模板,这部分是逆向迭代器实现的基础:【C++】模拟实现listicon-default.png?t=N7T8https://blog.csdn.net/weixin_72357342/article/details/140809635?spm=1001.2014.3001.5501


📌了解模拟实现reverse_iterator

        在本次项目中我们的目标是实现一个reverse_iterator(反向迭代器适配器):

        该reverse_iterator适配器底层是使用iterator来实现.

        reverse_iterator提供的功能有:

  1. reverse_iterator构造函数
  2. operator++函数重载
  3. operator++(int)函数重载
  4. operator--函数重载
  5. operator--(int)函数重载
  6. operator*函数重载
  7. operator->函数重载
  8. operator!=函数重载
  9. operator==函数重载

二.逐步实现项目功能模块及其逻辑详解

通过第一部分对项目功能的介绍,我们已经对reverse_iterator的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!


!!!注意,该部分的代码只是为了详细介绍某一部分的项目实现逻辑,故可能会删减一些与该部分不相关的代码以便大家理解,需要查看或拷贝完整详细代码的朋友可以移步本文第三部分。


📌实现reverse_iterator成员变量

        因为reverse_iterator的底层是用iterator来实现的,所以我们只需要定义一个iterator成员变量即可.但因为我们选择将reverse_iterator写成类模板,所以这里成员变量的类型是模板类型.

        其实可以理解为reverse_iterator的底层就是一个iterator,但我们通过类的特性,对iterator进行进一步的封装,使其行为符合reverse_iterator的行为,就完成了一个reverse_iterator类模板.

        注意,为了使迭代器成员及其函数可以直接被其他类使用,我们将其设为struct类.

        代码如下:

namespace mfc
{
	template<class Iterator, class Ref, class Ptr>
	struct reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;    //重定义缩短一下
		Iterator _it;        //成员变量

	};
}

📌实现reverse_iterator()构造函数

        构造函数很简单,就是用初始化列表把传入的iterator参数it赋值给_it即可,代码如下:

reverse_iterator(Iterator it)
	:_it(it)
{}

📌实现operator++函数重载

        因为是逆向遍历,reverse_iterator的++操作其实是底层iterator的--操作,我们直接调用iterator的函数接口即可,前置++返回++后的结果,所以我们操作完直接返回*this指针即可,代码如下:

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

📌实现operator++(int)函数重载

        因为是逆向遍历,reverse_iterator的++操作其实是iterator的--操作,我们直接调用iterator的函数接口即可,后置++要返回++前的结果,所以我们要提前设一个变量来记录++前的值,操作完直接返回该变量即可,代码如下:

self operator++(int)
{
	Iterator tmp = _it;
	--_it;
	return tmp;
}

📌实现operator--函数重载

        因为是逆向遍历,reverse_iterator的--操作其实是iterator的++操作,我们直接调用iterator的函数接口即可,前置--返回--后的结果,所以我们操作完直接返回*this指针即可,代码如下:

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

📌实现operator--(int)函数重载

        因为是逆向遍历,reverse_iterator的--操作其实是iterator的++操作,我们直接调用iterator的函数接口即可,后置--要返回--前的结果,所以我们要提前设一个变量来记录--前的值,操作完直接返回该变量即可,代码如下:

self operator--(int)
{
	Iterator tmp = _it;
	++_it;
	return tmp;
}

📌实现operator*函数重载

        因为我们在设计迭代器时是仿照STL源码对称设计的,所以我们的反向迭代器其实是指向对应结点的后一个位置的:

        那么正常情况下我们想要获得当前指针的值,就要去解引用该指针前一个位置的值,要解引用前一个位置,可以直接调底层iterator的*和--函数,注意*操作_it不能改变,所以我们创建一个变量tmp代替_it--,代码如下:

Ref operator*()
{
	Iterator tmp = _it;//解引用不动当前数据,但是要返回前一个数据的解引用,只有用一个变量来代替--了
	return *(--tmp);
}

📌实现operator->函数重载

        operator->操作就是获得迭代器指向的成员变量的地址,那我们可以直接调用解引用操作再取地址,代码如下:

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

📌实现operator!=函数重载

        判断迭代器不相等底层iterator类模板里已经支持了,我们直接调用即可,代码如下:

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

📌实现operator==函数重载

        判断迭代器相等底层iterator类模板里已经支持了,我们直接调用即可,代码如下:

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

三.项目完整代码

        因为模板定义和声明不能分离,所以我们将程序运行的代码分别在一个工程文件中编辑,完整代码如下:

📌ReverseIterator.h文件

namespace mfc
{
	template<class Iterator, class Ref, class Ptr>
	struct reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;
		Iterator _it;

		reverse_iterator(Iterator it)
			:_it(it)
		{}
		self operator++()
		{
			--_it;
			return *this;
		}
		self operator++(int)
		{
			Iterator tmp = _it;
			--_it;
			return tmp;
		}
		self operator--()
		{
			++_it;
			return *this;
		}
		self operator--(int)
		{
			Iterator tmp = _it;
			++_it;
			return tmp;
		}
		Ref operator*()
		{
			Iterator tmp = _it;//解引用不动当前数据,但是要返回前一个数据的解引用,只有用一个变量来代替--了
			return *(--tmp);
		}
		Ptr operator->()
		{
			return &(operator*());
		}
		bool operator!=(const self& s) const
		{
			return _it != s._it;
		}
		bool operator==(const self& s) const
		{
			return _it == s._it;
		}
	};
}

结语

希望这篇reverse_iterator的模拟实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++】模拟实现priority_queue(优先级队列)

【C++】模拟实现queue

【C++】模拟实现stack

【C++】模拟实现list

【C++】模拟实现vector

【C++】模拟实现string类

【C++】构建第一个C++类:Date类

【C++】类的六大默认成员函数及其特性(万字详解)

【C++】什么是类与对象?


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1991730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++综合项目】——基于Boost库的搜索引擎(手把手讲解,小白一看就会!!)

目录 一、前言 二、项目的相关背景 ⚡什么是Boost库&#xff1f;⚡ ⚡什么是搜索引擎&#xff1f;⚡ ⚡为什么要做Boost搜索引擎&#xff1f;⚡ 二、搜索引擎的宏观原理 三、搜索引擎技术栈和项目环境 四、正排索引 VS 倒排索引 —— 搜索引擎的具体原理 &#x…

leetcode22. 括号生成,DFS深度优先搜索

leetcode22. 括号生成 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 示例 2&am…

SQL面试题练习 —— 最后一次登录停留时长

目录 1 题目2 建表语句3 题解 题目来源&#xff1a;腾讯微信。 1 题目 有一张用户登录日志表ods_usr_login_log, 包含user_id&#xff08;用户id&#xff09;、ds&#xff08;登录时间&#xff09;以及stay_time&#xff08;停留时长&#xff0c;单位:ms&#xff09; 问题&…

再等等,iPhone 17系列大革新,即将带来颠覆性的升级

自从苹果在2021年的iPhone 13 Pro系列中引入了ProMotion自适应刷新率技术以来&#xff0c;这项技术便成为了高端智能手机显示技术的重要标志。 如今&#xff0c;随着iPhone 17系列即将登场&#xff0c;我们有望见证这项技术向下一代更广泛的设备拓展。不仅如此&#xff0c;iPh…

每日一题~ abc 365 E 异或运算(拆位+贡献)

处理位运算常用的方法&#xff1a; 拆位法&#xff08;一位一位的处理&#xff0c;通常题目中会给出元素的最大是2的的多少次幂&#xff0c;当然也有给10的次幂的&#xff0c;自己注意一下就可以了&#xff09; 常用的思想 &#xff1a; 算贡献。 异或的性质&#xff1a; A^A0 …

抖音外卖区域服务商有哪些城市开放了?搭建本地生活系统抢先入局的成功率如何?

随着多家互联网大厂对本地生活重视程度的不断提高&#xff0c;本地生活服务商逐渐成为众多创业者心目中的首选赛道。在此背景下&#xff0c;抖音外卖区域服务商的申请通道一经开放便引发了一阵申请热潮。 毕竟&#xff0c;根据艾瑞咨询数据预测&#xff0c;到2025年&#xff0…

Linux5.15.71编译问题处理

目录 1 编译环境及源码版本2 移植Linux 5.15.71遇到问题2.1 imx-sdma 20ec000.dma-controller: Direct firmware load for imx/sdma/sdma-imx6q.bin failed with error -22.2 cfg80211: failed to load regulatory.db 1 编译环境及源码版本 ​ 1. uboot-alientek-v2022.04 ​…

红酒与亚洲菜肴:品味东方韵味

当西方的红酒遇上东方的菜肴&#xff0c;一场跨越地域与文化的味蕾盛宴就此展开。洒派红酒&#xff08;Bold & Generous&#xff09;与亚洲菜肴的相遇&#xff0c;不仅是一场美食的邂逅&#xff0c;更是一次对东方韵味的深度品味。 一、红酒的醇厚与亚洲菜肴的精致 红酒&…

【Unity程序】和【控制台程序】连接【asp.net core的websocket服务】(1)——在编辑器中运行

一、说明 1、本文实验内容所涉及的开发环境说明&#xff1a; win11VisualStudio2022&#xff08;.Net6.0&#xff09;Unity2021.3.40 2、本文参考资料 【1】NativeWebSocketUnity包&#xff1a; https://github.com/endel/NativeWebSocket 【2】asp.net core架设websocket国…

【安卓】SharedPreferences存储

SharedPreferences使用键值对的方式来存储数据的。也就是说&#xff0c;当保存一条数据的时候&#xff0c;需要给这条数据提供一个对应的键&#xff0c;这样在读取数据的时候就可以通过这个键把相应的值取出来。而且SharedPreferences还支持多种不同的数据类型存储&#xff0c;…

游戏原画可节省60-80%工时,大厂在用AI做什么

AIGC技术的迭代&#xff0c;是不是太快了点&#xff1f; 前年年中还是光速出图的Stable Diffusion&#xff0c;到年底就有了可以媲美真人的文本处理模型ChatGPT&#xff0c;今年开年又蹦出来了可以凭空变出视频、动画的Sora……我们对技术升级的认知被一次次刷新&#xff0c;同…

BHGMall生活超市天通苑店盛大开业,多重好礼只等你来

据悉8月10日&#xff0c;BHGMall生活超市天通苑店焕新开业&#xff0c;催旺“七夕浪漫经济”造福社区百姓&#xff0c;不仅提供助老服务&#xff0c;还有超值福利、多重好礼&#xff0c;倡导天天有低价&#xff0c;以实惠的价格买到优质的商品&#xff0c;提升居民幸福感和城市…

解题思考:为什么Java中使用Arrays.stream()创建流处理数组通常会增加开销,提高时间复杂度?

目录 问题描述&#xff1a;问题回答&#xff1a; 问题描述&#xff1a; 在解决力扣上的&#xff1a; 3131. 找出与数组相加的整数 I 时&#xff0c;使用传统遍历会比创建流处理数组的时间复杂度更低。 1.传统遍历代码&#xff1a; class Solution {public int addedInteger(i…

大模型与数据分析的融合:创新与发展的新机遇

大模型与数据分析的融合&#xff1a;创新与发展的新机遇 前言大模型与数据分析的融合 前言 大模型与数据分析的融合正成为推动企业发展的关键力量。大模型在数据分析领域展现出了强大的能力。它能够以接近人类的水平理解和处理自然语言&#xff0c;快速、准确地解析大量非结构…

vue实现PC端图片放大缩小可鼠标拖动,鼠标滚轮控制放大缩小完整代码付效果图

vue实现图片放大缩小可鼠标拖动&#xff0c;鼠标滚轮控制放大缩小完整代码付效果图 效果图&#xff1a; 创建一个ImageViewer 组件&#xff0c;并且在当前页面引用完整代码如下&#xff1a; 代码引用&#xff1a; <template><view><image-viewer :imageUrl&q…

大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

SOMEIP_ETS_022:echoStaticUINT8Array_One_Dimensional

测试目的&#xff1a; 确保DUT能够正确处理一维静态UINT8数组参数&#xff0c;并且在发送和接收过程中保持参数值和顺序不变。 描述 本测试用例将验证DUT在处理包含一维静态UINT8数组参数的SOME/IP消息时&#xff0c;是否能够准确地发送和接收这些参数&#xff0c;确保返回的…

[数据结构] 万字解析排序算法

文章目录 快速排序双指针法整体排序过程整理选择基准值&#xff08;Pivot&#xff09;单趟划分&#xff08;Partitioning&#xff09;递归分治&#xff08;Divide and Conquer&#xff09;终止条件合并 整体代码实现为什么相遇位置一定是小值&#xff1f;情况 1: 右指针j找到了…

HexView 刷写文件脚本处理工具-基本功能介绍(七)-导出VBF/GM/GM-FBL

导出Ford VBF数据容器 VBF文件格式是Ford和Volvo Cars使用的多功能二进制格式。此文件的输出基于“Versatile Binary Format”规范,版本从2.2至2.5。在对话框中输入的所有值将被写入INI文件。INI文件也可以用于命令行选项,以在不需要用户输入的情况下生成输出。 导出GM数据…

网卡与Linux网络结构(中)

1 socket数据结构 socket源码 socket结构体是操作系统网络编程接口的一个核心组件。在操作系统中&#xff0c;socket结构体定义了一个网络连接的抽象&#xff0c;包括文件描述符、地址信息、连接状态等。 socket结构体代码位于<include/linux/net.h> struct socket { s…