C++中的reverse_iterator迭代器结构设计

目录

reverse_iterator迭代器结构设计

reverse_iterator迭代器基本结构设计

operator*()函数

operator++()函数

operator->()函数

operator!=()函数

rbegin()函数

rend()函数

operator--()函数

operator==()函数

测试代码

const_reverse_iterator迭代器设计

reverse_iterator迭代器结构设计思路改进


reverse_iterator迭代器结构设计

前面的list类以及vector类设计了正向迭代器,现在考虑设计反向迭代器,常规的设计思路为单独为反向迭代器建一个新类,这个类中所有的函数全部重新设计,这种思路可取但是并不高效,可以考虑下面的设计思路:

前面了解到了容器适配器,那么是否也可以把正向迭代器设置为反向迭代器的容器适配器从而实现反向迭代器的效果

对于此时的反向迭代器类设计即为如下:

以list类为例

reverse_iterator迭代器基本结构设计

//反向迭代器template<classIterator>class_list_reverse_iterator{typedef_list_reverse_iterator self;//使用正向迭代器构造反向迭代器_list_reverse_iterator(Iterator it):_it(it){}​private:Iterator_it;};

operator*()函数

首先是对于operator*()函数来说,解引用操作符获得的结果即为指针当前指向中的内容,而在正向迭代器中,解引用操作符也是同样的作用,所以此处可以复用正向迭代器的解引用操作符,但是此处是Iterator类对象,所以不能使用传统的直接对内置类型解引用的方式,但是可以考虑直接调用Iterator类中的operator*()函数

对于返回值来说,可以考虑和设计const版本的正向迭代器思路一致,使用模板参数区分传递T&T*

所以修改原来的类定义为:

//反向迭代器template<class Iterator, class Ref, class Ptr>class _list_reverse_iterator{typedef _list_reverse_iterator self;//使用正向迭代器构造反向迭代器_list_reverse_iterator(Iterator it):_it(it){}​private:Iterator _it;};

此时的operator*()函数即为如下设计:

//operator*()函数Ref operator*(){return _it.operator*();}

operator++()函数

对于前置++运算符来说,不同于正向迭代器,因为正向迭代器++是从第一个有效数据节点开始一直到头节点结束,而对于反向迭代器来说,其++是从最后一个有效数据节点开始向前一直到头节点结束,如下图所示:

但是可以考虑通过正向迭代器适配出反向迭代器,具体思路如下:

begin()放置在最后一个有效数据节点的位置,即end()-1的位置,将end()放在头节点的位置即可

所以,operator++()函数可以设计为

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

operator->()函数

operator*()函数一样,调用Iterator中的operator->()函数即可

//operator->()函数Ptr operator->(){return _it.operator->();}

operator!=()函数

同正向迭代器中的设计思路一致

//operator!=()函数
bool operator!=(self& s)
{return _it != s._it;
}

rbegin()函数

//rbegin()函数——反向——非const版本
reverse_iterator rbegin()
{//因为正向迭代器中没有重载-,所以使用--代替return reverse_iterator(--end());
}

rend()函数

//rend()函数——反向——非const版本
reverse_iterator rend()
{return reverse_iterator(end());
}

operator--()函数

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

operator==()函数

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

测试代码

此时基本的反向迭代器框架已经搭建完成,下面是测试代码:

void test_reverse_iterator()
{sim_list::list<int> ls;ls.push_back(1);ls.push_back(2);ls.push_back(3);ls.push_back(4);ls.push_back(5);sim_list::list<int>::reverse_iterator rit = ls.rbegin();while (rit != ls.rend()){cout << *rit << " ";++rit;}
}

const_reverse_iterator迭代器设计

对于const_reverse_iterator设计来说,不需要更改reverse_iterator迭代器的结构,只需要在list类中重定义一个const版本即可

typedef _list_reverse_iterator<iterator, T&, T*> reverse_iterator;// 反向迭代器——非const版本
typedef _list_reverse_iterator<iterator, const T&, const T*> const_reverse_iterator // 反向迭代器——const版本

并且将rbegin()rend()分别重载一个const版本

//rbegin()函数——反向——const版本
reverse_iterator rbegin() const
{//因为正向迭代器中没有重载-,所以使用--代替//注意end()此处是常量,但是此处是调用了operator--(),所以可以调用(编译器对const类型能调用普通函数的优化),如果是内置指针类型则必须写成end()-1return reverse_iterator(--end());
}//rend()函数——反向——const版本
reverse_iterator rend() const
{return reverse_iterator(end());
}

reverse_iterator迭代器结构设计思路改进

前面在设计reverse_iterator迭代器时,直接考虑的rbegin()函数的位置在最后一个有效节点的位置,而rend()在则在end()的位置,这样的思路并没有错误,但是参照SGI版本中的设计:

rbegin()rend()设计

可以看出,SGI版本在设计rbegin()rend()时考虑到和begin()end()形成了一种对称关系,如下图所示:

那么此时SGI版本中的反向迭代器是如何处理operator*()函数的

配合rbegin()rend()遍历思路如下:

取出上一个有效节点的数据,因为rbegin()在头节点的位置,所以先取出最后一个节点的数据,迭代器--操作到最后一个有效节点,一直到rend()位置结束

参考完SGI版本的迭代器设计,此时可以对上面的设计进行优化为SGI版本

//operator*()函数
Ref operator*()
{Iterator cur = _it;//如果不实现--,也可以用-1来代替return *(--cur);
}//rbegin()函数——反向——非const版本
reverse_iterator rbegin()
{//因为正向迭代器中没有重载-,所以使用--代替return reverse_iterator(end());
}//rend()函数——反向——非const版本
reverse_iterator rend()
{return reverse_iterator(begin());
}//rbegin()函数——反向——const版本
reverse_iterator rbegin() const
{//因为正向迭代器中没有重载-,所以使用--代替return reverse_iterator(end());
}//rend()函数——反向——const版本
reverse_iterator rend() const
{return reverse_iterator(begin());
}

此时对于operator->()函数来说,则需要换一个实现思路:直接取当前operator*()结果的地址

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安全再升级,亚信安慧AntDB数据库与亚信安全二次牵手完成兼容性互认证

日前&#xff0c;湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧&#xff09;的产品与亚信科技&#xff08;成都&#xff09;有限公司&#xff08;简称&#xff1a;亚信安全&#xff09;再次携手&#xff0c;完成亚信安慧AntDB数据库与亚信安全IPoE接入认证系统…

Ftrans文件外发系统 构建安全可控文件外发流程

文件外发系统是企业数据安全管理中的关键组成部分&#xff0c;它主要用于处理企业内部文件向外部传输的流程&#xff0c;确保数据在合法、安全、可控的前提下进行外发。 文件外发系统的主要作用包括&#xff1a; 1、防止数据泄露&#xff1a;通过严格的审批流程和安全策略&…

节能洗车房车牌识别项目实战

项目背景 学电子信息的你加入了一家节能环保企业&#xff0c;公司的主营产品是节能型洗车房。由于节水节电而且可自动洗车&#xff0c;产品迅速得到了市场和资本的认可。公司决定继续投入研发新一代产品&#xff1a;在节能洗车房的基础上实现无人值守的功能。新产品需要通过图…

Altium Designer——第一课

一个电子设计包含四个部分&#xff1a; 1.原理图库的设计 2.原理图的设计 3.PCB封装库的设计 4.PCB布局和PCB布线的设计 电子设计工程包含的部分&#xff1a; Free documents&#xff1a; 在我们保存AD工程的文件夹中&#xff0c;如果打开的是prjpcb后缀的工程文件&#xf…

《Fundamentals of Power Electronics》——基础交流建模方法

PWM整流器小信号交流模型建模的主要步骤为&#xff1a; (a)利用小纹波近似的动态版本&#xff0c;建立与电感和电容波形的低频平均值有关的方程&#xff1b; (b)平均方程的扰动和线性化&#xff1b; (c)交流等效电路模型的建立。 以下图buck-boost电路为例进行分析。 首先测…

二叉树的迭代遍历 | LeetCode 144. 二叉树的前序遍历、LeetCode 94. 二叉树的中序遍历、LeetCode 145. 二叉树的后序遍历

二叉树的前序遍历&#xff08;迭代法&#xff09; 1、题目 题目链接&#xff1a;144. 二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#x…

【Java】实现一个简单的线程池

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 ​编辑 一、线程池的模式 二、线程池的一些参数 三、代码实现 1.BlockingQueue 2.ThreadPool 四、拒绝策略 一、线程池的模式 线程池顾名思义就是管理线程的一个池子&#xff0c;我们把创建线程的过程交给…

Neo4j v5 中 Cypher 的变化

How Cypher changed in Neo4j v5 Neo4j v5 中 Cypher 的变化 几周前&#xff0c;Neo4j 5 发布了。如果你像我一样&#xff0c;在 Neo4j 4 的后期版本中忽略了所有的弃用警告&#xff0c;你可能需要更新你的 Cypher 查询以适应最新版本的 Neo4j。幸运的是&#xff0c;新的 Cyp…

SpringBoot自定义定时任务

通常&#xff0c;在我们的项目中需要定时给前台发送一些提示性消息或者我们想要的定时信息&#xff0c;这个时候就需要使用定时任务来实现这一功能&#xff0c;实现也很简单&#xff0c;接下来具体来看看吧~ 简单定时任务 首先&#xff0c;你需要在你的启动类上加上开启定时任…

Python-VBA函数之旅-oct函数

目录 一、oct函数的常见应用场景 二、oct函数使用注意事项 三、如何用好oct函数&#xff1f; 1、oct函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、oct函数的常见应用场景 oc…

docker部署nginx并实现https

文章目录 docker部署nginx并实现https1、服务器环境2、安装docker3、准备证书4、准备nginx配置文件和dockerfile文件5、创建nginx镜像与容器6、验证访问 docker部署nginx并实现https 1、服务器环境 [rootliuyanfen12 ~]#systemctl stop firewalld [rootliuyanfen12 ~]#setenf…

WORD排版常见问题与解决方案

前言 近期使用word软件进行论文排版工作&#xff0c;遇到了一些常见的问题&#xff0c;记录一下&#xff0c;避免遗忘。 基本配置 系统环境&#xff1a;win10/win11 word版本&#xff1a;Microsoft Office LTSC 专业增强版 2021 问题与解决方案 问题1&#xff1a;页眉显示内…

【STM32F407+CUBEMX+FreeRTOS+lwIP netconn UDP TCP记录】

STM32F407CUBEMXFreeRTOSlwIP netconn UDP TCP记录 注意UDPUDP1UDP2 TCPTCP clientTCP server图片 注意 1、超时 #include “lwipopts.h” #define LWIP_SO_RCVTIMEO 12、先保证能ping通 3、关于工程创建可参考 【STM32F407CUBEMXFreeRTOSlwIP之UDP记录】 4、…

C语言之数据结构之栈和队列的运用

目录 1. 用队列实现栈1.1 思路讲解1.2 代码实现 2. 用栈实现队列1.1 思路讲解1.2 代码实现 总结 •͈ᴗ•͈ 个人主页&#xff1a;御翮 •͈ᴗ•͈ 个人专栏&#xff1a;C语言数据结构 •͈ᴗ•͈ 欢迎大家关注和订阅!!! 1. 用队列实现栈 题目描述&#xff1a; 请你仅使用两个…

恶补《操作系统》5_2——王道学习笔记

5.2_1 I-O核心子系统 1、用户层软件 假脱机系统 2、设备独立性软件&#xff08;设备无关性软件&#xff09; IO调度、设备保护、设备分配与回收、缓冲区管理 3、设备驱动程序&#xff08;比如打印机驱动&#xff09; 4、中断处理程序 5、硬件 5.2_2 假脱机技术&#xff…

小程序引入 Vant Weapp 极简教程

一切以 Vant Weapp 官方文档 为准 Vant Weapp 官方文档 - 快速入手 1. 安装nodejs 前往官网下载安装即可 nodejs官网 安装好后 在命令行&#xff08;winr&#xff0c;输入cmd&#xff09;输入 node -v若显示版本信息&#xff0c;即为安装成功 2. 在 小程序根目录 命令行/终端…

www.fastssh.com SSH over WebSockets with CDNs

https://www.fastssh.com/page/create-ssh-cdn-websocket/server/这其实不是标准的websocket报文(服务器响应报文无Sec-Websocket-Accept字段)&#xff0c;所以无法使用github.com/gorilla/websocket包&#xff1a;GET / HTTP/1.1 Host: hostname:8080 User-Agent: Go-http-cli…

jvm重要参数可视化和线上问题排查

jvm重要参数可视化和线上问题排查 目标jvm参数分类(了解)运行时数据区相关的&#xff08;jdk1.8&#xff09;处理 OOM 相关的垃圾回收器相关的GC 日志记录相关的意义,默认值,调优原则&#xff08;重要&#xff0c; 待拆分&#xff09; 排查 OOM 流程 和 常见原因参考文章 目标 …

【除了协程还有哪些方式可以实现异步编程】

在Unity中&#xff0c;除了使用协程实现异步编程外&#xff0c;还有以下几种方法&#xff1a; 异步加载资源&#xff1a; 使用UnityWebRequest类进行异步加载资源&#xff0c;这在加载网络资源或动态加载资源时非常有用。 using UnityEngine; using UnityEngine.Networking;…

基于OpenCv的图像特征点检测

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…