当前位置: 首页 > 编程日记 > 正文

设计1.0 -- iterator 和const_iterator底层的模拟实现

本文概要:

本文主要是模拟实现STL中迭代器和const迭代器的,主要阐述的一个问题就是,为什么我们在设计迭代器的时候需要使用三个模板参数呢

在设计迭代器的时候,我们有下面的代码

#include<iostream>
using namespace std;template<class T>
struct _ListNode
{_ListNode<T>* _next;_ListNode<T>* _prev;T _data;_ListNode(T d = 0):_data(d), _next(NULL), _prev(NULL){}
};//这个T标记的是维护的数据类型,Ref是引用,这个引用是对数据的引用,就是这里面data的引用
//Ptr是指针,这个指针也是指向数据data的指针这两个模板类型我们可以在
//List这个类里面使用,因为在编写List_Iterator的时候,会经常使用Ref和Ptr
template<class T, class Ref, class Ptr>
class List_Iterator
{typedef _ListNode<T> Node;typedef List_Iterator<T, Ref, Ptr> Self;   //这个地方写的 有点失误了,就是把List_Iterator的单词写错了
public:List_Iterator(Node* it):_it(it){}//List_Iterator& operator++()Self& operator++(){_it = _it->_next;return *this;}Self operator++(int)    //注意前置++返回的是引用,而后置++返回的是Self{Node* tmp = _it;_it = _it->_next;return tmp;}//T& operator*()Ref operator*(){return _it->_data;}bool operator!=(const Self& it){return _it != it._it;    //一开始写这个!=运算符重载的时候也出现了错误,就是我一开始是拿this和&it比//这显然是不对的,两个迭代器不可能是相等的,所以这个时候应该是拿//这两个迭代器所指向的内容来比较,就是那他们的成员变量来 进行比较才正确}private:Node* _it;
};//这里我们需要做一个修改就是,我们需要把这个链表定义成一个双向的有头的循环链表
//这个工作就是要在构造函数的时候去做了
//所以这里_tail就不需要了//有头结点,_head维护了一个头结点,但是这个节点不放置任何的数据,因为这样在后面的增删查改的时候使用的时候会非常的方便
template<class T>
class _List
{typedef _ListNode<T> Node;public:typedef List_Iterator<T, T&, T*> Ierator;//const迭代器typedef List_Iterator<T, const T&, const T*> Const_Ierator;_List():_head(new Node)   //这里报了一个错误就是,没有合适的构造函数可以使用,原因是我上面写_ListNode的时候//传参了,但是这里没有传参数,所以我上面的额时候把传递的参数默认为d = 0这个时候就算是我不传递参数//也没有什么问题了//  , _tail(_head){_head->_next = _head;_head->_prev = _head;}Node* begin(){if (_head->_next == _head)   //这里做了一个判断就是当我们的链表是空的时候,就不能直接返回next{return NULL;}return _head->_next;}Node* end(){if (_head->_next == _head){return NULL;}return _head;}void Pushback(const T& data){Node* cur = new Node(data);cur->_prev = _head->_prev;_head->_prev = cur;cur->_next = _head;cur->_prev->_next = cur;}void Print(){Const_Ierator it = begin();   //这个原因是,我们的begin不是 const的,但是我们的const_ietator是const的while (it != end()){cout << *it << endl;it++;}}
private:Node* _head;
//  Node* _tail;
};void TestList()
{_List<int> l;l.Pushback(0);   //一开始的时候,我这里设置的这个参数是引用,这个时候是辩不过的,因为我们的0是在常量区的l.Pushback(1);l.Pushback(2);/*_List<int>::Ierator it = l.begin();cout << *it << endl;++it;cout << *it << endl;++it;cout << *it << endl;*/_List<int>::Ierator it = l.begin();*it = 5;l.Print();}

这里想重点比较一下普通迭代器和const迭代器,这里我们想看我们的普通迭代器的定义,

template<class T, class Ref, class Ptr>
class List_Iterator
{typedef _ListNode<T> Node;typedef List_Iterator<T, Ref, Ptr> Self;   //这个地方写的 有点失误了,就是把List_Iterator的单词写错了
public:List_Iterator(Node* it):_it(it){}//List_Iterator& operator++()Self& operator++(){_it = _it->_next;return *this;}Self operator++(int)    //注意前置++返回的是引用,而后置++返回的是Self{Node* tmp = _it;_it = _it->_next;return tmp;}//T& operator*()Ref operator*(){return _it->_data;}bool operator!=(const Self& it){return _it != it._it;    //一开始写这个!=运算符重载的时候也出现了错误,就是我一开始是拿this和&it比//这显然是不对的,两个迭代器不可能是相等的,所以这个时候应该是拿//这两个迭代器所指向的内容来比较,就是那他们的成员变量来 进行比较才正确}private:Node* _it;
};

这里只是一个普通的迭代器的实现,一开始我一直疑惑的一个问题就是,为什么这里在设计的时候需要设计三个模板参数 呢,因为是为了实现迭代器的复用,这个时候还是需要看一下我们的list中对于迭代器的使用

class _List
{typedef _ListNode<T> Node;public:typedef List_Iterator<T, T&, T*> Ierator;//const迭代器typedef List_Iterator<T, const T&, const T*> Const_Ierator;_List():_head(new Node)   

这里我只截图了迭代器的一部分,想看全部的可以从上面来看,这里需要定义一个普通的迭代器的时候,使用typedef List_Iterator

Ref operator*(){return _it->_data;}

因为我们在list中使用的时候是按照下面的形式进行组织的

typedef List_Iterator<T, const T&, const T*> Const_Ierator;

所以在上面的那个Ref operator*()里面 返回值就变成了const的,这个时候const_iterator所指向的内容就不可变了

相关文章:

关于python缩进的描述中_关于Python程序中与“缩进”有关的说法中,以下选项中正确的是()...

关于Python程序中与“缩进”有关的说法中,以下选项中正确的是()答&#xff1a;缩进在程序中长度统一且强制使用同文学或同音乐主题的民歌&#xff0c;《_______》是其中之一。此曲经民间艺人丁喜才改编后&#xff0c;由上海音乐学院鞠秀芳于50年代在国际上唱红答&#xff1a;五…

使用Newtonsoft.Json

首先是前一段某博友对于循环引用的问题的解决&#xff1a;http://www.cnblogs.com/Gryzor/archive/2013/05/06/3062373.html 其次是时间到底是UTC还是Local的问题&#xff1a;http://www.cnblogs.com/leonwang/archive/2013/05/29/javascript-datetime.html 对于第二条&#xf…

回击质疑 HP StoreOnce用高性能说话

四五年以前&#xff0c;记者曾经两次参观过惠普位于英国西南部港口城市布里斯托尔的存储研究中心&#xff0c;那里是惠普数据备份和保护产品的大本营&#xff0c;同时也是惠普磁带产品与HP StoreOnce产品家族的诞生地。就在惠普刚刚发布升级版的HP StoreOnce B6200以及Catalyst…

windows10配置jenkins

1、下载pscp.exe并拷贝到c:\window\system32&#xff0c;此工具用于上传文件至linux服务器 下载地址&#xff1a;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 2、下载jenkins.war 下载地下&#xff1a;https://jenkins.io/download/ 3、设置环境变量JENKI…

STL模拟实现1.0 -- list和iterator模拟实现和简单分析

引言 C 标准模本库《STL》中有很多优秀的代码实现&#xff0c;不然怎么能叫做C标准模板库呢&#xff0c;其中一个实现就是有一个容器&#xff0c;叫做list。所谓容器其实就是存储相同类型数据的一个存储集合&#xff0c;list的底层实现其实就是一个链表。 我们的普通数组在使…

hdc mfc 画扇形图_使用echarts绘制条形图和扇形图

使用echarts绘制条形图和扇形图简单举例说明下echarts如何绘制条形图和扇形图代码示例echarts绘制条形图和扇形图var mychart1echarts.init(document.getElementById(chart1),light);// 指定图表的配置项和数据var option {title: {text: ECharts 入门示例},tooltip: {},legen…

Java学习笔记45:Java 线程与主线程之间的变量关系

运行下面的代码&#xff1a; package com.test.www;public class Test {public static int count 0;public static void inc() {//这里延迟1毫秒&#xff0c;使得结果明显try {Thread.sleep(1);} catch (InterruptedException e) {}count;}public static void main(String[] a…

会计的思考(36):会计--企业运营的数码相机

新浪网上看到一张图片&#xff0c;拍的是2009年12月3日的武汉市&#xff0c;整个城市在笼罩在一片污浊空气当中&#xff0c;让人震惊。虽然我在深圳&#xff0c;但也清楚好不到哪去。 震惊之余&#xff0c;感谢新浪&#xff0c;更感谢某位摄影师&#xff0c;让我们了解到生活的…

spring cloud连载第二篇之Spring Cloud Config

Spring Cloud Config Spring Cloud Config为分布式服务提供了服务侧和客户侧的外部配置支持。通过Spring Cloud Config你可以有一个统一的地方来管理所有应用的外部配置。 默认服务端存储实现用的是git&#xff0c;因此&#xff0c;它很容易支持配置环境的标签版本&#xff0c;…

CodeOnly

关于设置[Key]标志 要先添加 程序集的引用 在添加 using System.ComponentModel.DataAnnotations; 命名控件转载于:https://www.cnblogs.com/since87/archive/2013/06/09/3129399.html

继承和多态 2.0 -- 继承的六个默认成员函数

本文重要介绍普通继承中如何写派生类的六个默认成员函数&#xff0c;主要是针对在派生类中&#xff0c;如何调用基类的六个默认成员函数 需要说明的一点就是&#xff0c;如果子类中没有调用父类的函数时&#xff0c;系统会自动生成一个。 构造函数 子类中有父类的成员&#…

js 让鼠标右下角有一排小字_js布局中一排大字下面接着一排小字怎么打出来?...

展开全部可以使用 TypewriterJS 实现效果是这样 ,百度图片少了一部分&#xff0c;可以通过链接32313133353236313431303231363533e78988e69d8331333433626438看效果链接: 网页链接示例在这里: 网页链接文档地址: 网页链接使用步骤引用 TypewriterJShtmlcss.article__title {fon…

Hudson神奇的环境变量

Hudson神奇的环境变量 http://blog.sina.com.cn/s/blog_798f21a00100z6zw.html转载于:https://blog.51cto.com/myloveworld/950156

英语影视台词---四、Sideways

英语影视台词---四、Sideways 一、总结 一句话总结&#xff1a;杯酒人生 Sideways&#xff0c;大致意思是“偏离、倾斜、转向…”。很明显中文译名与英文原名并没有什么关联&#xff0c;《杯酒人生》这个名字&#xff0c;其实也可以译为《并肩前行》&#xff0c;应该是从影片内…

继承和多态 3.0 -- 菱形继承

单继承和多继承 C的继承方式是支持单继承和多继承的&#xff0c;首先看一下代码&#xff0c;分清单继承和多继承 单继承 class A { public:int _a; };class B :public A { public:int _b; };class C : public A { public:int _c; }; 类似于上面的方式就是单继承&#xff0c;或…

C# split 几种使用方法

第一种方法&#xff1a; string s "abcdeabcdeabcde"; string[] sArray s.Split(c); foreach (string i in sArray) Console.WriteLine(i.ToString()); Console.ReadKey();输出下面的结果:abdeabdeabd…

模糊匹配 读音_onenote搜索机制详解②:两种搜索模式,模糊与精确匹配

先从纯文本搜索讲起&#xff0c;这是最基本也是最重要的。从这篇开始&#xff0c;以及接下来连续几篇文章&#xff0c;都会介绍搜索的基础功能。注意&#xff0c;这几篇文章中谈论的都是基本的、正常的搜索功能&#xff0c;暂时不考虑Bug等因素。在很多软件&#xff08;例如wor…

EXT3与EXT4的主要区别

Linux kernel 自 2.6.28 开始正式支持新的文件系统 Ext4。 Ext4 是 Ext3 的改进版&#xff0c;修改了 Ext3 中部分重要的数据结构&#xff0c;而不仅仅像 Ext3 对 Ext2 那样&#xff0c;只是增加了一个日志功能而已。Ext4 可以提供更佳的性能和可靠性&#xff0c;还有更为丰富的…

Java IO 4 : RandomAccessFile

RandomAccessFile:   认识&#xff1a;java输入/输出流体系中功能最丰富的文件内容访问类 既可以读取文件内容&#xff0c;也可以向文件传输数据&#xff0c;并且支持“随机访问“的方式&#xff0c;程序可以跳转到任意地方来读写数据。 特点&#xff1a;与OutputStream/Writ…

二叉树 1.0 -- 创建二叉树、遍历二叉树、二叉树常见问题求解

树的结构主要是为了查找&#xff0c;这个主要是为了搜索&#xff0c;树的结构关注的不是增删查改 树 广义上面的树的结构我们不知道树的一个节点是有几个子节点的&#xff0c;所以这个时候我们需要定义的一种结构就是&#xff0c;一个节点的孩子是可以动态的增加的&#xff0…

impala 本年格式化时间_hive,hbase,impala之间的对比

hbase在三者中更注重的是存储&#xff0c;它实现了类似mysql的double write机制&#xff0c;但是它是一种NoSQL的数据库&#xff0c;并且是可以支持列式存储的&#xff0c;算是比较大的一个内存Hash表。hbase也采用了类似mysql中的mvcc的思想通过时间戳来做版本控制。hbase是在…

简单上手的游戏引擎

物理游戏引擎 GameSalad 转载于:https://www.cnblogs.com/sgdkg/archive/2013/06/14/3135882.html

Linux内核中关于定时器Timer的应用

2019独角兽企业重金招聘Python工程师标准>>> 在Touchscreen驱动中 1 声明 Ad7877.c (\linux-2.6.30.4\drivers\input\touchscreen): struct timer_list timer; /* P: lock */ 2 初始化 在函数 static int __devinit ad7877_probe(struct spi_device *spi) 中 执行 …

类加载过程中几个重点执行顺序整理

类的加载过程&#xff1a; 1、 JVM会先去方法区中找有没有相应类的.class存在。如果有&#xff0c;就直接使用&#xff1b;如果没有&#xff0c;则把相关类的.class加载到方法区 2、 在.class加载到方法区时&#xff0c;会分为两部分加载&#xff1a;先加载非静态内容&#xff…

二叉树 2.0 -- 非递归遍历

二叉树递归遍历存在的问题 如果我们的二叉树只有左子树&#xff0c;而且树的高度还很深的时候&#xff0c;这个时候递归调用遍历的时候&#xff0c;栈帧空间开辟的较大&#xff0c;很可能造成栈溢出。但是我们一个程序中&#xff0c;为堆分配的空间要比栈大的多&#xff0c;这…

田忌赛马贪心算法_田忌赛马 贪心算法

算法实验课回顾田忌赛马问题描述&#xff1a;你一定听说过田忌赛马的故事吧&#xff1f;如果3匹马变成n匹(n<100)&#xff0c;齐王仍然让他的马按照优到劣的顺序初赛&#xff0c;田忌可以按任意顺序选择他的赛马出赛。赢一局&#xff0c;田忌可以得到200两银子&#xff1b;输…

[转][小结][三种方法]实现WPF不规则窗体

实现WPF不规则窗体的三种常用的方法如下&#xff1a; 1.使用Blend等工具绘制一个不规则xaml&#xff0c;然后作为窗体的背景。这个可以参考xiaowei0705的这篇博文&#xff1a;WPF制作不规则的窗体 。 2.给window的Clip属性赋Path值。这个可以参考DebugLZQ前面的博文&#xff1a…

VirtualBox虚拟机网络连接设置的四种方式

这里我先给大家大致讲解下VBox的网络配置及应用。 VirtualBox的提供了四种网络接入模式&#xff0c;它们分别是&#xff1a;1、NAT 网络地址转换模式(NAT,Network Address Translation)2、Bridged Adapter 桥接模式3、Internal 内部网络模式4、Host-only Adapter 主机…

redis-deskmanager 连不上 虚拟机 - centos redis

1、没设置redis密码 &#xff1a; https://blog.csdn.net/HUXU981598436/article/details/54668779 2、关闭防火墙 转载于:https://www.cnblogs.com/Jomini/p/9650650.html

数据库1.0 -- 数据库的基本操作

安装数据库 安装数据库的时候我们需要安装三个软件&#xff0c;使用下面的命令&#xff0c;可能还会出现一些问题&#xff0c;关于数据库的安装&#xff0c;大家可以上网自行百度 yum install mysql yum install mysql-server yum install mysql-devel 我个人的理解大概是这…