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

news2024/11/25 6:38:41

在上篇文章中,实现了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;
}

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

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

相关文章

grafana安装DevOpsProdigy KubeGraf 1.5.2

安装DevOpsProdigy KubeGraf需要安装kube-state-metrics 官方地址&#xff1a;https://github.com/kubernetes/kube-state-metrics/tree/release-2.10/examples/standard 查看k8s版本和kube-state-metrics对应版本&#xff1a; [rootmaster1 kube-state-metrics]# ll 总用量 …

25考研|660/880/1000/1800全年带刷计划

作为一个参加过两次研究生考试的老学姐&#xff0c;我觉得考研数学的难度完全取决于你自己 我自己就是一个很好的例子 21年数学题目是公认的简单&#xff0c;那一年考130的很多&#xff0c;但是我那一年只考了87分。但是22年又都说是有史以来最难的一年&#xff0c;和20年的难度…

华擎B660 主板 怎么设置打开来电自启功能?

环境&#xff1a; 华擎B660 钢铁传奇 1700 : Intel B660 问题描述&#xff1a; 华擎B660 主板 怎么设置打开来电自启功能&#xff1f; 解决方案&#xff1a; 1.前往-高级- 芯片组配置 2.往下划找到交流 /电源断电恢复 选择电源故障后的电源状态。如果选择 [关机]&#x…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(4)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;3&#xff09; 4.1.2 PCIe总线使用的信号 PCIe设备使用两种电源信号供电&#xff0c;分别是Vcc与Vaux&#xff0c;其额定电压为3.3V。其中Vcc为主电源&#xff0c;PCIe设备…

免费分享一套SpringBoot+Vue药店(药房)管理系统,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue药店(药房)管理系统 &#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue药店(药房)管理系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue药店(药房)管理系统 Java毕业设计…

flutter实战之美化 container

我们来看一个代码 Column(children: [...transaction.map((e) > Card(child:Row(children: [Container(child: Text(e.amout.toString()),),Column(children: [Text(e.title),Text(e.date.toString()),],)],),)).toList()],) 看看效果 感觉很不好 我们要去美化一下contai…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 为了答谢各位网友的支持&#xff0c;从今日起…

pytorch_car_caring 排坑记录

pytorch_car_caring 排坑记录 任务踩坑回顾简单环境问题代码版本问题症状描述解决方法 cuda问题&#xff08;异步问题&#xff09;症状描述解决方法 任务 因为之前那个MPC代码跑出来的效果不理想&#xff0c;看了一天代码&#xff0c;大概看明白了&#xff0c;但要做改进还要有…

力扣hot100 对称二叉树 递归

Problem: 101. 对称二叉树 文章目录 思路Code 思路 &#x1f468;‍&#x1f3eb; 参考 Code 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* …

Pytorch从零开始实战18

Pytorch从零开始实战——人脸图像生成 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——人脸图像生成环境准备模型定义开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytorch2.0.1cu118&#…

jmerter-01安装与界面介绍

文章目录 jmeter安装 jmeter安装 1.配置JDK环境 Jmeter到目前为止只支持java 8 2.解压JMeter安装包 就可以双击jmeter.bat 运行启动 3.运行过程中&#xff0c;不要关掉小黑窗 这个黑框不要关闭 jmeter图示

【CSS】外边距折叠(margin 塌陷)

外边距折叠(collapsing margins) 毗邻的两个或多个margin会合并成一个margin&#xff0c;叫做外边距折叠。 规则如下: 两个或多个毗邻的普通流中的块元素垂直方向上的 margin会折叠浮动元素 / inline-block元素 / 绝对定位元素 / 行内元素的margin不会和垂直方向上的其他元素…

使用Logstash将MySQL中的数据同步至Elasticsearch

目录 1 使用docker安装ELK 1.1 安装Elasticsearch 1.2 安装Kibana 1.3 安装Logstash 2 数据同步 2.1 准备MySQL表和数据 2.2 运行Logstash 2.3 测试 3 Logstash报错(踩坑)记录 3.1 记录一 3.1.1 报错信息 3.1.2 报错原因 3.1.3 解决方案 3.2 记录二 3.2.1 报错信…

深入了解C++:底层编译原理

进程的虚拟空间划分 任何编程语言&#xff0c;都会产生两样东西&#xff0c;指令和数据。 .exe程序运行的时候会从磁盘被加载到内存中&#xff0c;但是不能直接加载到物理内存中。Linux会给当前进程分配一块空间&#xff0c;比如x86 32位linux环境下会给进程分配2^32(4G)大小…

《数字电子电路》 课程设计:十字路口红绿灯自动控制系统(上)(multisim仿真及PCB实现)

&#xff08;一&#xff09;前言 本系列文章就笔者在大二下学期进行《数字电子线路》课程设计的题目&#xff1a;十字路口红绿灯自动控制系统 进行详细的讲解&#xff0c;希望对读者有所帮助。 &#xff08;二&#xff09;目录 一、主要指标及要求 二、电路工作原理 1、工作原…

「数据结构」3.ArrayList

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;Java数据结构 &#x1f387;**欢迎点赞收藏加关注哦&#xff01;* ArrayList &#x1f349;ArrayList的构造&#x1f349;add方法&#x1f34c;扩容机制&#x1f34c;重要结论 &#x1f349;其…

大数据交易蓝图,推动数据价值实现

数据最为新的生产要素&#xff0c;必定会推动各行各业的革新和转型。 数据流通&#xff0c;是数据价值实现的必然之路。 大数据交易中心&#xff0c;提供数据产品挂牌出售和合法合规交易的场所和平台。 数据厂商&#xff0c;通过技术手段收集数据&#xff0c;实现数据标准化…

idea配置tomcat

推荐链接&#xff1a;IntelliJ IDEA中配置Tomcat&#xff08;超详细&#xff09;_idea怎么配置tomcat服务器-CSDN博客 1,官员下载链接&#xff1a;Apache Tomcat - Welcome! 附本人下载的 tomcat9 的百度网盘链接 链接&#xff1a;https://pan.baidu.com/s/1DpyBGnG4mUGTm5Z…

【Django开发】0到1开发美多商城项目第3篇:用户注册业务实现(附代码,已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现前后端…

[Java面试]JavaSE知识回顾

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Java面试中JavaSE中会涉及到的知识点 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x…