反向迭代器------封装的力量

目录

一、list封装中模板参数Ref和Ptr的理解

二、反向迭代器的实现



一、list封装中模板参数Ref和Ptr的理解

        对于反向迭代器,是我们在前面STL模拟实现中留下的一个问题。在之前的文章中,我们极大程度上的利用了模板,从而减少了许多的代码,如今我们的反向迭代器也是利用了封装+模板的思想,将正向迭代器包装成为了通用的反向迭代器。

        首先我们来看看之前list模拟实现的代码

namespace hmy
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& x = T()):_data(x), _next(nullptr), _prev(nullptr){}};// T T& T*// T cosnt T& const T*template<class T, class Ref, class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;Node* _node;__list_iterator(Node* node):_node(node){}self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prev;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const self& s){return _node != s._node;}bool operator==(const self& s){return _node == s._node;}};template<class T>class list{typedef list_node<T> Node;public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}//这里是传值返回,是一个临时对象,而临时对象具有常性,在以后的使用中不能--,需要写成-1等iterator begin(){return iterator(_head->_next);//return _head->_next;}iterator end(){return iterator(_head);//return _head;}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto e : lt){push_back(e);}}// lt3 = lt1/*list<int>& operator=(const list<int>& lt){if (this != &lt){clear();for (auto e : lt){push_back(e);}}return *this;}*/void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}// lt3 = lt1list<int>& operator=(list<int> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}void pop_back(){erase(--end());}iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* newnode = new Node(x);Node* prev = cur->_prev;// prev newnode curprev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return iterator(newnode);}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;delete cur;prev->_next = next;next->_prev = prev;--_size;return iterator(next);}size_t size(){return _size;}private:Node* _head;size_t _size;};}

        之前我们的list模拟实现利用了list_node__list_iterator以及list这三个类互相封装来实现代码,其中list_node是链表的节点结构体;__list_iterator是链表的迭代器的结构体;list是封装他们两个结构体的类,这样就构成了list的框架。其中list_node只需要封装节点的关键信息:数据和前后指针;__list_iterator则只需要封装迭代器的成员和相关函数(例如++和--还有*解引用等)。而他们的融合则产生了化学一般的反应----------各个类各司其职,结构分明的组成了一个更加完善更加方便的类----list。而list只需要做的就是把对外的成员函数写出即可(比如begin/end/构造/插入和删除等),至于其他底层的实现则交给了__list_iterator和list_node。这就是封装的力量!

        关于模板参数Ref和Ptr的补充讲解:

        在实例化对象list1的时候就已经明确了他是const对象还是普通对象,然后在调用成员函数的时候,编译器会根据它的类型来确定是调用const修饰的成员函数还是调用普通函数,不论调用的是const修饰的函数还是普通函数,都会先走迭代器的构造函数这一关,(因为他们都是__list_iterator<T, Ref, Ptr>的特殊形式,所以走的都是同一个构造函数)他们在这里将_node赋值为了传入的node值,但是在这里他们已经确定了Ref和Ptr的区别,const_iterator传入的参数是T/const T&/const T*于是这里的Ref和Ptr就分别是const T&和const T*,所以他们在后续的使用中也会产生截然不同的效果

二、反向迭代器的实现

言归正传:

        我们的反向迭代器也用到了封装这一核心思想。他为了代码层面的简略,将正向迭代器封装到其中,然后再利用正向迭代器的成员函数就能够轻而易举的实现反向迭代器了。(同样是使用了Ref和Ptr来区别const反向迭代器和普通迭代器)

        

于是我们只需要在list这个类中补充关于两个反向迭代器的声明和一些成员函数即可正常使用了

        值得注意的是,反向迭代器中的第一个模板参数竟然是一个正向迭代器!!!这其实被我们称为适配器模式,他会跟着我们传入不同类型的迭代器而产生不一样的适配模式,如果传入的参数是list<int>::iterator那么他适配出来的就是list<int>的反向迭代器等等.......

下面是测试代码:

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

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

相关文章

09、全文检索 -- Solr -- SpringBoot 整合 Spring Data Solr (生成DAO组件 和 实现自定义查询方法)

目录 SpringBoot 整合 Spring Data SolrSpring Data Solr的功能&#xff08;生成DAO组件&#xff09;&#xff1a;Spring Data Solr大致包括如下几方面功能&#xff1a;Query查询&#xff08;属于半自动&#xff09;代码演示&#xff1a;1、演示通过dao组件来保存文档1、实体类…

B3668 [语言月赛202210] 应急食品

题目背景 派蒙是不是应急食品&#xff1f;不同的旅行者有不同的答案。 题目描述 派蒙是不是应急食品&#xff0c;是每一个旅行者必须完成的选择题。 选项 A 为 派蒙是应急食品&#xff1b; 选项 B 为 派蒙不是应急食品。 旅行者一定是正确的&#xff0c;现在告诉你某个旅行…

SpringCloud之Feign发送Http请求

文章目录 http客户端Feign使用步骤自定义Feign的配置Feign的性能优化Feign的性能优化-连接池配置 Feign的最佳实践 http客户端Feign Feign的介绍&#xff1a; Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;https:/github.com/OpenFeign/feign 其作用就是帮助…

人群异常聚集监测系统-聚众行为检测与识别算法---豌豆云

聚众识别系统对指定区域进行实时监测&#xff0c;当监测到人群大量聚集、达到设置上限时&#xff0c;立即告警及时疏散。 旅游业作为国民经济战略性支柱产业&#xff0c;随着客流量不断增加&#xff0c;旅游景区和一些旅游城市的管理和服务面临着前所未有的挑战&#xff1a; …

上海历年社保平均工资

标签&#xff1a; 上海历年平均工资&#xff1b; 上海历年社保最低工资&#xff1b; 备注&#xff1a; 上海最低社保按平均工资60%缴纳。上海社保最高基数为平均工资的3倍。公司裁员或者公司违约解除劳动合同&#xff0c;每月补偿工资不超过平均工资的3倍。 年份平均工资&…

使用 Spring Data JPA 和 Mybatis 结合的方式进行分页查询

文章目录 1. Spring Data JPA 和 Mybatis 操作数据库的区别1.1 Spring Data JPA1.2 Mybatis 2. 使用 Spring Data JPA 和 Mybatis 结合的方式进行分页查询2.1 创建实体类2.2 创建实体操作的 Repository 接口2.3 创建 Mybatis 的 Mapper 接口2.4 创建 Mybatis 的 Mapper XML 文件…

laravel_进程门面_简单介绍

文章目录 Facade是什么&#xff1f;Facade能干什么Facade有哪些方法&#xff1f;怎么使用Facade呢&#xff1f;详细的代码解释Symfony Process是什么&#xff1f;介绍Symfony总结 Facade是什么&#xff1f; 在 Laravel 框架中&#xff0c;Facade 是一种设计模式。 它提供了一…

476. Number Complement(数字的补数)

问题描述 对整数的二进制表示取反&#xff08;0 变 1 &#xff0c;1 变 0&#xff09;后&#xff0c;再转换为十进制表示&#xff0c;可以得到这个整数的补数。 例如&#xff0c;整数 5 的二进制表示是 “101” &#xff0c;取反后得到 “010” &#xff0c;再转回十进制表示…

java8默认方法

口什么是默认方法 口如何以一种兼容的方式改进API 口默认方法的使用模式 口 解析规则 传统上&#xff0c;Java程序的接口是将相关方法按照约定组合到一起的方式。实现接口的类必须为接口中定义的每个方法提供一个实现&#xff0c;或者从父类中继承它的实现。但是&#xff0c;一…

NLP_Transformer架构

文章目录 Transformer架构剖析编码器-解码器架构各种注意力的应用Transformer中的自注意力Transformer中的多头自注意力Transformer中的编码器-解码器注意力Transformer中的注意力掩码和因果注意力 编码器的输入和位置编码编码器的内部结构编码器的输出和编码器-解码器的连接解…

springboot/ssm防疫物资管理信息系统Java物资申请出入库系统

springboot/ssm防疫物资管理信息系统Java物资申请出入库系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7&…

STM32-寄存器和HAL库以及如何使用

在电子工程领域&#xff0c;“寄存库”和“HAL库”都是与微控制器&#xff08;MCU&#xff09;编程紧密相关的概念。 寄存器&#xff08;Register&#xff09; 含义&#xff1a; 在电子工程领域&#xff0c;特别是计算机体系结构和微控制器设计中&#xff0c;寄存器是一种非常…

计网物理层

通信基础 基本概念 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。 其主要任务是确定与传输媒体接口有关的一些特性&#xff0c;即定义标准。 机械特性&#xff1a;定义物理连接的特性&#xff0c;规定物理连接时所采用的…

模型 4R(关联、反应、关系、回报)理论

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。以关系促营销。 1 4R(关联、反应、关系、回报)理论的应用 1.1 4R模型在小米客户关系管理中的应用 小米公司是一家以生产智能手机和消费电子产品而闻名的公司&#xff0c;它在客户关系管理…

windows用powershell调亮度

有时夜晚将亮度调到最暗&#xff0c;早上想调回来时太暗又看不到&#xff0c;想写一个脚本调。参考 [1,2]&#xff0c;可用 powershell 命令实现。顺便记录 powershell 脚本参数写法。 Code # brightness.ps1# 命令行参数 b&#xff0c;[0, 100]&#xff0c;默认 50 param ($…

排序刷题8

题目来源&#xff1a;[NOIP2009 普及组] 分数线划定 - 洛谷 解题思路&#xff1a; 解题思路 这道题可以用STL库中的sort&#xff08;&#xff09;函数对选手成绩排序&#xff0c;并用bool类型的函数&#xff0c;输出比较结果。然后根据规定的录取比例&#xff08;计划录取人…

VMware Workstation 17.0 虚拟机安装MS-DOS 7.1完整详细步骤图文教程

VMware Workstation 17.0 虚拟机安装MS-DOS 7.1完整详细步骤图文教程 一、配置MS-DOS虚拟机机器环境二、安装MS-DOS磁盘操作系统 一、配置MS-DOS虚拟机机器环境 1.打开VMware Workstation Pro 2.新建虚拟机 3.建议选择【典型】&#xff0c;之后点击【下一步】 关于【自定义…

实现钉钉自定义机器人推送markdown类型消息

以前有一段时间普通群聊不支持创建自定义机器人&#xff0c;最近好像又可以了&#xff0c;遂发一篇文章讲解一下流程 创建机器人 首先在需要添加机器人的群里添加机器人&#xff0c;选择自定义机器人&#xff0c;创建成功之后记录webhook地址&#xff0c;安全策略可自行选择&…

【代码随想录算法训练营Day17】● 110.平衡二叉树;● 257. 二叉树的所有路径;● 404.左叶子之和

文章目录 Day 17 第六章 二叉树part04110.平衡二叉树 &#xff08;优先掌握递归&#xff09;基础递归思路递归代码 257. 二叉树的所有路径 &#xff08;优先掌握递归&#xff09;递归思路递归代码 404.左叶子之和 &#xff08;优先掌握递归&#xff09;思路自己的思路&#xff…

在spring中操作Redis

目录 创建项目 ​编辑 配置Redis 创建类 StringRedisTemplate set / get list set Hash zset 新年快乐&#xff01;&#xff01;&#xff01;&#xff01; 创建项目 选中maven项目&#xff0c;然后选择java8&#xff0c;输入名称之后&#xff0c;点击next。 随后选择…