C++(17.5)——list模拟实现扩展

在上篇文章中,实现了list的大部分功能以及部分迭代器。本片文章将对剩下的功能进行补充。

1. const迭代器:

对于上篇文章中实现的迭代器只能使用于非const类型的对象。对于const类型的遍历,则需要额外编写const类型的迭代器。例如对于下面的场景:

void print_list(const list<int>& s)
	{
		list<int>::const_iterator it2 = s.begin();
		while (it2 != s.end())
		{
			cout << *it2;
			it2++;
		}
	}

对于const与非const类型的变量的区别,是const类型的对象不能修改。因此,实现const迭代器的第一种方法,便是将非const迭代器的相关代码进行复制然后进行改动,基于const类型本身的性质,只需要将operator*()函数的返回值类型改为const类型即可,对应代码如下:

template<class T>
	struct __list_const_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_const_iterator<T> self;
		__list_const_iterator(Node* node)
			: _node(node)
		{}

		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		self& operator++(int)
		{
			self tmp(_node);
			_node = _node->_next;
			return tmp;
		}

		const T& operator*()
		{
			return _node->_data;
		}

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

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

		Node* _node;
	};

在完成上述步骤后,还需要在list中,引入__list_const_iterator,并且为了方便书写,利用typedef函数将其改写为const_iterator。将成员函数begin(),end()进行复制,然后改为const成员函数,代码如下:

const_iterator begin() const
		{
			return _phead->_next;
		}

		const_iterator end() const
		{
			return _phead;
		}

 此时,再运行上方给出的代码:

void print_list(const list<int>& s)
	{
		list<int>::const_iterator it2 = s.begin();
		while (it2 != s.end())
		{
			cout << *it2;
			it2++;
		}
	}
print_list(It);

 运行结果如下:

上述步骤虽然可以实现const迭代器的使用,但是两种迭代器的代码重复率过高。只有二者的成员函数operator*()的返回值类型不同,以及迭代器名称不同。为了简化上述代码,可以使用两个模板参数,即:

template<class T,class Ref>
	struct __list_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_iterator<T,Ref> self;
		__list_iterator(Node* node)
			: _node(node)
		{}

		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		self& operator++(int)
		{
			self tmp(_node);
			_node = _node->next;
			return tmp;
		}

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

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

		Node* _node;
	};

 其中,第二个模板参数Ref用于表示返回类型是const还是非const。并且,对list中引入的迭代器类型,通过传递不同的参数来进行区分,即:

template<class T>
	class list
	{
		typedef ListNode<T>  Node;
	public:
		typedef __list_iterator<T,T&> iterator;
		typedef __list_iterator<T,const T&> const_iterator;
		
		iterator begin()
		{
			return _phead->_next;
		}

		iterator end()
		{
			return _phead;
		}
		
		const_iterator begin() const
		{
			return _phead->_next;
		}

		const_iterator end() const
		{
			return _phead;
		}


		
		Node* _phead;
	};

2. 代码总览:
 

#include<assert.h>
#include<iostream>
using namespace std;


namespace violent
{
	template<class T>
	struct ListNode
	{
		ListNode(const T& x = T())
			: _prev(nullptr)
			, _next(nullptr)
			, _data(x)
		{}
		
		ListNode<T>* _prev;
		ListNode<T>* _next;
		T _data;
	};

	template<class T,class Ref>
	struct __list_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_iterator<T,Ref> self;
		__list_iterator(Node* node)
			: _node(node)
		{}

		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		self& operator++(int)
		{
			self tmp(_node);
			_node = _node->_next;
			return tmp;
		}

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

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

		T* operator->()
		{
			return &_node->_data;
		}
		Node* _node;
	};


	/*template<class T>
	struct __list_const_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_const_iterator<T> self;
		__list_const_iterator(Node* node)
			: _node(node)
		{}

		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		self& operator++(int)
		{
			self tmp(_node);
			_node = _node->_next;
			return tmp;
		}

		const T& operator*()
		{
			return _node->_data;
		}

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

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

		Node* _node;
	};*/

	template<class T>
	class list
	{
		typedef ListNode<T>  Node;
	public:
		typedef __list_iterator<T,T&> iterator;
		typedef __list_iterator<T,const T&> const_iterator;
		list()
		{
			_phead = new Node;
			_phead->_next = _phead;
			_phead->_prev = _phead;
		}

		void empty()
		{
			_phead = new Node;
			_phead->_next = _phead;
			_phead->_prev = _phead;
		}

		list(const list<T>& s)
		{
			empty();
			for (auto e : s)
			{
				push_back(e);
			}
		}

		void swap(list<T>& s)
		{
			std::swap(_phead, s._phead);
		}

		list<T>& operator=(list<T> s)
		{
			swap(s);
			return *this;
		}

		iterator begin()
		{
			return _phead->_next;
		}

		iterator end()
		{
			return _phead;
		}
		
		const_iterator begin() const
		{
			return _phead->_next;
		}

		const_iterator end() const
		{
			return _phead;
		}


		/*void push_back(const T& x)
		{
			Node* newnode = new Node(x);
			Node* tail = _phead->_prev;
			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _phead;
			_phead->_prev = newnode;
		}*/

		void push_back(const T& x)
		{
			insert(_phead, x);
		}

		void push_front(const T& x)
		{
			insert(_phead->_next, x);
		}

		void insert(iterator pos,const T& x)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* newnode = new Node(x);

			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
		}

		void pop_back()
		{
			erase(_phead->_prev);
		}

		void pop_front()
		{
			erase(_phead->_next);
		}

		iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;

			delete cur;
			return next;
		}

		void clear()
		{
			iterator i2 = begin();
			while (i2 != end())
			{
				i2 = erase(i2);
			}
		}


		~list()
		{
			clear();

			delete _phead;
			_phead = nullptr;
		}
		Node* _phead;
	};

	void print_list(const list<int>& s)
	{
		list<int>::const_iterator it2 = s.begin();
		while (it2 != s.end())
		{
			cout << *it2;
			it2++;
		}
	}

	

	void test1()
	{
		list<int> It;
		It.push_back(1);
		It.push_back(2);
		It.push_back(3);
		It.push_back(4);
		list<int>::iterator it1 = It.begin();
		while (it1 != It.end())
		{
			cout << *it1 << ' ';
			++it1;
		}
		cout << endl;
		It.insert(It.begin(), 5);
		It.insert(It.begin(), 6);
		It.insert(It.begin(), 7);
		It.insert(It.begin(), 8);
		It.push_front(9);
		It.push_front(9);
		It.push_front(9);
		
		for (auto e : It)
		{
			cout << e << ' ';
		}

		cout << endl;
		It.pop_back();
		It.pop_back();
		It.pop_front();
		It.pop_front();
		for (auto e : It)
		{
			cout << e << ' ';
		}

		cout << endl;
		cout << "const迭代器:";
		print_list(It);

	

	}
	struct AA
	{
		AA(int aa1 = 1, int aa2 = 2)
			: _aa1(aa1)
			, _aa2(aa2)
		{}

		int _aa1;
		int _aa2;
	};

	void test3()
	{
		AA a(2, 3);
		list<AA> It;

		It.push_back(a);
		It.push_back(AA());
		It.push_back(AA(1, 2));

		list<AA>::iterator it = It.begin();
		while (it != It.end())
		{
			cout << it->_aa1 << endl;
			it++;
		}
	}
}

#include"list_1.h"

int main()
{
	violent::test3();
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Yolo v8 入门学习之采用 coco128 数据集进行图片检测测试

示例入门代码 from ultralytics import YOLO import cv2 import matplotlib.pyplot as plt import matplotlib.image as mpimgdef test():# Create a new YOLO model from scratchmodel YOLO(yolov8n.yaml)# Load a pretrained YOLO model (recommended for training)model …

在Windows系统中执行DOS命令

目录 一、用菜单的形式进入DOS窗口 二、通过IE浏览器访问DOS窗口 三、复制、粘贴命令行 四、设置窗口风格 1.颜色 2.字体 3.布局 4.选项 五、Windows系统命令行 由于Windows系统彻底脱离了DOS操作系统&#xff0c;所以无法直接进入DOS环境&#xff0c;只能通过第三方软…

从零开始 Linux(一):基础介绍与常用指令总结

从零开始 Linux 01. 概念理解 1.1 什么是 Linux&#xff1f; Linux 是一个开源免费的 操作系统&#xff0c;具有很好的稳定性、安全性&#xff0c;且有很强的处理高并发的能力 Linux 的应用场景&#xff1a; 可以在 Linux 下开发项目&#xff0c;比如 JavaEE、大数据、Python…

css多行文本擦拭效果

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>多行文本擦拭效果</title><style>* …

QT SQL

QT SQL模块提供数据库编程的支持&#xff0c;支持多种常见的数据库&#xff1a;MySQL\Oracle\MS SQL Server\SQLite等。SQL模块包含多个类&#xff0c;可以实现&#xff1a;数据库连接、SQL语句执行、数据获取与界面显示 等功能。数据 与 界面间用Model\View架构。 一、 二、Q…

网络服务综合实验项目

目录 实验要求 运行环境 基础配置 业务需求 实验步骤 一、基础配置 1.1、配置静态IP 1.1.1、 在192.168.159.130中配置 1.1.2、 在192.168.159.131中配置 ​编辑 1.2、修改主机名及hosts映射 1.2.1、在192.168.159.130中配置 1.2.2、 编辑配置hosts文件 1.2.3、重启…

用的到的linux-文件移动-Day2

前言&#xff1a; 在上一节&#xff0c;我们复习了cd大法和创建生成文件和文件夹的方法&#xff0c;介绍了一些“偷懒”&#xff08;高效&#xff09;的小技巧&#xff0c;本节&#xff0c;我们一起来探讨下&#xff0c;我们对文件移动操作时有哪些可以偷懒的小技巧~ 一、复制…

社科院与杜兰大学金融管理硕士项目——金融硕士学位证书有多重要呢

随着金融行业的快速发展&#xff0c;金融管理硕士项目逐渐成为越来越多人追求高学历和提升职业竞争力的选择。其中&#xff0c;社科院与杜兰大学合作的金融管理硕士项目备受关注。然而&#xff0c;对于很多人来说&#xff0c;花费大量的时间和金钱去攻读一个硕士学位是否值得呢…

前端开发实战基础——模块

文章目录 概要模块标识符模块依赖模块加载入口 CommonJS语法单例 AMD语法 UMD核心语法 ES6模块化模块标签及定义模块导出和导入命名导出和导入默认导出和导入命名导出和默认导出混用 模块行为 小结 概要 模块化&#xff0c;就是将代码拆分成独立的块&#xff0c;各自在代码块中…

小白初探|神经网络与深度学习

一、学习背景 由于工作的原因&#xff0c;需要开展人工智能相关的研究&#xff0c;虽然不用参与实际研发&#xff0c;但在项目实施过程中发现&#xff0c;人工智能的项目和普通程序开发项目不一样&#xff0c;门槛比较高&#xff0c;没有相关基础没法搞清楚人力、财力如何投入&…

Linux实验记录:使用Apache的虚拟主机功能

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 正文&#xff1a; 目录 前言&#xff1a; 正文&…

每日一道Java面试题:说一说Java中的泛型?

写在开头 今天的每日一道Java面试题聊的是Java中的泛型&#xff0c;泛型在面试的时候偶尔会被提及&#xff0c;频率不是特别高&#xff0c;但在日后的开发工作中&#xff0c;却是是个高频词汇&#xff0c;因此&#xff0c;我们有必要去认真的学习它。 泛型的定义 什么是泛型…

2024年1月的论文推荐

又到月底了&#xff0c;在月初推荐论文的基础上又整理了10篇推荐阅读的论文 1、MosaicBERT https://mosaicbert.github.io/ 一种用于快速预训练的双向编码器。MosaicBERT是针对快速预训练优化的自定义BERT架构。主要架构修改:FlashAttention, ALiBi&#xff0c;门控线性单元…

(八)MySQL事务和SQL优化

事务&#xff08;Transaction&#xff09;&#xff1a; 是数据库内最小且不可再分的单元。通常一个事务对应一个完整的业务(例如银行账户转账业务&#xff0c;该业务就是一个最小的工作单元)。一个完整的业务由批量的DML语句&#xff08;INSERT 、UPDATE、DELETE&#xff09;共…

pinctrl子系统与gpio子系统实验-通过应用程序测试Led驱动程序

一. 简介 前面几篇文章基本完成了 Led驱动代码&#xff0c;前面通过加载驱动模块也测试了 驱动程序。 这里通过运行应用程序&#xff0c;通过应用程序调用 Led驱动程序&#xff0c;从而驱动 打开或者关闭 Led灯。 二. 通过应用程序测试Led驱动程序 1. 驱动代码实现 gpiole…

【Qt】—— 项⽬⽂件解析

目录 &#xff08;一&#xff09;.pro⽂件解析 &#xff08;二&#xff09;widget.h⽂件解析 &#xff08;三&#xff09;main.cpp⽂件解析 &#xff08;四&#xff09;widget.cpp⽂件解析 &#xff08;五&#xff09;widget.ui⽂件解析 &#xff08;一&#xff09;.pro⽂…

Sg5032can(晶体振荡器spxo)规格书

SG5032CAN是爱普生推出的一款小体积尺寸5.0x3.2mm石英晶体振蒎器&#xff0c;四脚贴片晶振&#xff0c;输出频率范围为4MHz~72MHz,电源电压1.8V ~ 3.3V&#xff0c;支持CMOS输出&#xff0c;具有超小型&#xff0c;轻薄型&#xff0c;高精度&#xff0c;高性能&#xff0c;高品…

(二)hadoop搭建

1. 下载 访问https://hadoop.apache.org/releases.html查看hadoop最新下载地址 wget https://dlcdn.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz 2.解压 tar zxvf hadoop-3.3.4.tar.gz mv hadoop-3.3.4 /usr/local 3.配置环境变量&#xff08;新建.sh文件&…

【网站项目】066农家乐信息平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

面向对象(基础)---面向对象编程概述、Java语言的基本元素:类和对象

学习面向对象内容的三条主线&#xff1a; ①Java类及类的成员&#xff1a;&#xff08;重点&#xff09;属性、方法、构造器&#xff1b;&#xff08;熟悉&#xff09;代码块、内部类 ②面向对象的特征&#xff1a;封装、继承、多态、&#xff08;抽象&#xff09; ③其他关…