C++初阶——简单实现list

news2025/2/25 8:24:36

目录

1、前言

2、List.h

3、Test.cpp


1、前言

1. 简单实现std::list,重点:迭代器,类模板,运算符重载。

2. 并不是,所有的类,都需要深拷贝,像迭代器类模板,只是用别的类的资源,不需要深拷贝。

3. 高度相似 -> 模板。

4. 迭代器的种类

功能:iterator,reverse_iterator,const_iterator,const_reverse_iterator。

按结构(性质):决定可以使用什么算法

单向(Forward):forward_list/unordered_map/unordered_set    ++

双向(Bidirectional):list/map/set    ++/--

随机(Random Access):vector/string/deque    ++/--/+/-

2、List.h

#pragma once

#include <iostream>
#include <list>
#include <assert.h>

using namespace std;

namespace Lzc
{
	template<class T>
	struct list_node
	{
		typedef list_node<T> Node;
		T _data;
		Node* _next;
		Node* _prev;
		list_node(const T& data = T())
			:_data(data)
			, _next(nullptr)
			, _prev(nullptr)
		{}
	};

	//template<class T>
	//struct list_iterator
	//{
	//	typedef list_node<T> Node;
	//	typedef list_iterator<T> iterator;
	//	Node* _node;
	//	list_iterator(Node* node)
	//		:_node(node)
	//	{}
	//	T& operator*() const
	//	{
	//		return _node->_data;
	//	}
	//	T* operator->() const
	//	{
	//		return &_node->_data;
	//	}
	//	iterator& operator++() // 前置++
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	iterator operator++(int) // 后置++
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	iterator& operator--() // 前置--
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	iterator operator--(int) // 后置--
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const iterator& it) const
	//	{
	//		return _node != it._node;
	//	}
	//  bool operator==(const iterator& it) const
	//	{
	//		return _node == it._node;
	//	}
	//};

	//template<class T>
	//struct list_const_iterator
	//{
	//	typedef list_node<T> Node;
	//	typedef list_const_iterator<T> const_iterator;
	//	Node* _node;
	//	list_const_iterator(Node* node)
	//		:_node(node)
	//	{
	//	}
	//	const T& operator*() const
	//	{
	//		return _node->_data;
	//	}
	//	const T* operator->() const
	//	{
	//		return &_node->_data;
	//	}
	//	const_iterator& operator++() // 前置++
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	const_iterator operator++(int) // 后置++
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	const_iterator& operator--() // 前置--
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	const_iterator operator--(int) // 后置--
	//	{
	//		iterator tmp(_node);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	bool operator!=(const const_iterator& it) const
	//	{
	//		return _node != it._node;
	//	}
	// 	bool operator==(const const_iterator& it) const
	//	{
	//		return _node == it._node;
	//	}
	//};

	// 高度相似->模板
	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)
		{}
		Ref operator*() const
		{
			return _node->_data;
		}
		Ptr operator->() const
		{
			return &_node->_data;
		}
		Self& operator++() // 前置++
		{
			_node = _node->_next;
			return *this;
		}
		Self operator++(int) // 后置++
		{
			Self tmp(_node);
			_node = _node->_next;
			return tmp;
		}
		Self& operator--() // 前置--
		{
			_node = _node->_prev;
			return *this;
		}
		Self operator--(int) // 后置--
		{
			Self tmp(_node);
			_node = _node->_prev;
			return tmp;
		}
		bool operator!=(const Self& it) const
		{
			return _node != it._node;
		}
		bool operator==(const Self& it) const
		{
			return _node == it._node;
		}
	};

	template<class T>
	class list
	{
		typedef list_node<T> Node; // 只有list类的成员函数或者友元才能使用这个类型别名
	public:
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;
		//typedef list_iterator<T> iterator;
		//typedef list_const_iterator<T> const_iterator;

		iterator begin()
		{
			return _head->_next; // 隐式类型转换
		}
		iterator end()
		{
			return _head;
		}
		const_iterator begin() const
		{
			return _head->_next;
		}
		const_iterator end() const
		{
			return _head;
		}

		void empty_initialize()
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;
			_size = 0;
		}
		list()
		{
			empty_initialize();
		}
		list(initializer_list<T> lt)
		{
			empty_initialize();
			for (auto& e : lt)
			{
				push_back(e);
			}
		}
		list(const list& lt)
		{
			// list();构造函数不能被直接调用
			empty_initialize();
			for (auto& e : lt)
			{
				push_back(e);
			}
		}

		void swap(list& tmp)
		{
			std::swap(_head, tmp._head);
			std::swap(_size, tmp._size);
		}
		list& operator=(const list& lt)
		{
			list tmp(lt);
			swap(tmp);
			return *this;
		}

		void clear()
		{
			while (!empty())
			{
				pop_front();
			}
		}

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
			_size = 0;
		}

		size_t size() const
		{
			return _size;
		}

		bool empty() const
		{
			return _size == 0;
		}

		void push_back(const T& val)
		{
			insert(end(), val);
		}

		void push_front(const T& val)
		{
			insert(begin(), val);
		}

		iterator insert(iterator pos, const T& val);

		void pop_front()
		{
			erase(begin());
		}
		void pop_back()
		{
			erase(_head->_prev);
		}

		iterator erase(iterator pos);

	private:
		Node* _head;
		size_t _size;
	};

	template<class T>
	typename list<T>::iterator list<T>::insert(iterator pos, const T& val)
	{
		Node* newNode = new Node(val);
		Node* cur = pos._node;
		Node* prev = cur->_prev;

		prev->_next = newNode;
		newNode->_prev = prev;
		newNode->_next = cur;
		cur->_prev = newNode;

		++_size;

		return newNode;

	}

	template<class T>
	typename list<T>::iterator list<T>::erase(iterator pos)
	{
		assert(pos != _head);
		Node* cur = pos._node;
		Node* next = cur->_next;
		Node* prev = cur->_prev;

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

		--_size;

		return next;
	}

	template<class Container>
	void print_Container(const Container& con)
	{
		for (auto& e : con)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

3、Test.cpp

#include "List.h"

namespace Lzc
{
	struct AA
	{
		int _a1 = 1;
		int _a2 = 1;
	};
	void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);

		list<int>::iterator it = lt.begin();
		while (it != lt.end())
		{
			*it += 10;

			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
		print_Container(lt);

		list<AA> lta;
		lta.push_back(AA());
		lta.push_back(AA());
		lta.push_back(AA());
		lta.push_back(AA());
		list<AA>::iterator ita = lta.begin();
		while (ita != lta.end())
		{
			//cout << (*ita)._a1 << ":" << (*ita)._a2 << endl;
			cout << ita->_a1 << ":" << ita->_a2 << endl;

			// 特殊处理,本来应该是两个->才合理,为了可读性,省略了一个->
			// cout << ita.operator->()->_a1 << ":" << ita.operator->()->_a2 << endl;
			
			++ita;
		}
		cout << endl;
	}

	void test_list2()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);

		// insert后,it还指向begin(),没有扩容的概念,不失效
		list<int>::iterator it = lt.begin();
		lt.insert(it, 10); 
		*it += 100;

		print_Container(lt);

		// erase后,it为野指针,及时更新
		// 删除所有的偶数
		it = lt.begin();
		while (it != lt.end())
		{
			if (*it % 2 == 0)
			{
				it = lt.erase(it);
			}
			else
			{
				++it;
			}
		}

		print_Container(lt);
	}

	void test_list3()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		list<int> lt2(lt1);

		print_Container(lt1);
		print_Container(lt2);

		list<int> lt3;
		lt3.push_back(10);
		lt3.push_back(20);
		lt3.push_back(30);
		lt3.push_back(40);

		lt1 = lt3;
		print_Container(lt1);
		print_Container(lt3);
	}

	void func(const list<int>& lt)
	{
		print_Container(lt);
	}

	void test_list4()
	{
		// 直接构造
		list<int> lt0({ 1,2,3,4,5,6 });
		// 隐式类型转换
		list<int> lt1 = { 1,2,3,4,5,6,7,8 };
		const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };

		func(lt0);
		func({ 1,2,3,4,5,6 });

		print_Container(lt1);

		// template<class T> class initializer_list;
		// { 10, 20, 30 }是一种initializer_list<int>类型
		//auto il = { 10, 20, 30 };
		//initializer_list<int> il = { 10, 20, 30 };
		//cout << typeid(il).name() << endl;
		//cout << sizeof(il) << endl;
	}
}

int main()
{
	Lzc::test_list1();
	Lzc::test_list2();
	Lzc::test_list3();
	Lzc::test_list4();
	return 0;
}

注意:声明和定义分离时,为什么定义时,是list<T>::iterator,不是iterator,因为iterator在list<T>中typedef了,就属于list<T>的成员变量了。

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

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

相关文章

linux 命令+相关配置记录(持续更新...)

linux 命令记录相关配置记录 磁盘切换 cd D&#xff1a;#这里表示切换到D盘查看wsl 安装的linux 子系统 wsl --list -vwsl 卸载 linux 子系统 wsl --unregister -xxx # xxx 表示子系统的名字备份Linux 子系统 导出 wsl --export xxx yyy # xxx 表示子系统的名字 yyy 表示压…

【PDF预览】使用iframe实现pdf文件预览,加盖章

使用iframe实现pdf文件预览&#xff0c;以及在pdf上添加水印。另外还包括批注、打印、下载、缩放、分页等功能 <iframesrc"http://static.shanhuxueyuan.com/test.pdf"width"100%"height"100%"frameborder"0"></iframe>&l…

网络运维学习笔记(DeepSeek优化版)002网工初级(HCIA-Datacom与CCNA-EI)子网划分与协议解析

文章目录 子网划分与协议解析1. VLSM与CIDR技术解析1.1 VLSM&#xff08;Variable Length Subnetwork Mask&#xff0c;可变长子网掩码&#xff09;1.2 CIDR&#xff08;Classless Inter-Domain Routing&#xff0c;无类域间路由&#xff09; 2. 子网划分方法与计算2.1 常规划分…

在线骑行|基于SpringBoot的在线骑行网站设计与实现(源码+数据库+文档)

在线骑行网站系统 目录 基于SpringBoot的在线骑行设计与实现 一、前言 二、系统设计 三、系统功能设计 5.1用户信息管理 5.2 路线攻略管理 5.3路线类型管理 5.4新闻赛事管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取…

BUUCTF-Web方向21-25wp

目录 [HCTF 2018]admin弱口令session伪造 [MRCTF2020]你传你&#x1f40e;呢[护网杯 2018]easy_tornado[ZJCTF 2019]NiZhuanSiWei[MRCTF2020]Ez_bypass第一层第二层 [HCTF 2018]admin 打开环境&#xff0c;有三处提示&#xff0c;一个跳转链接&#xff0c;一个登录注册&#x…

软考——WWW与HTTP

1.万维网&#xff08;world wide web&#xff09; 是一个规模巨大的、可以资源互联的资料空间。由URL进行定位&#xff0c;通过HTTP协议传送给使用者&#xff0c;又由HTML来进行文件的展现。 它的主要组成部分是&#xff1a;URL、HTTP、HTML。 &#xff08;1&#xff09;URL…

GO 进行编译时插桩,实现零码注入

Go 编译时插桩 Go 语言的编译时插桩是一种在编译阶段自动注入监控代码的技术&#xff0c;目的是在不修改业务代码的情况下&#xff0c;实现对应用程序的监控和追踪。 基本原理 Go 编译时插桩的核心思想是通过在编译过程中对源代码进行分析和修改&#xff0c;将监控代码注入到…

为人工智能驱动的交通研究增强路面传感器数据采集

论文标题 英文标题&#xff1a;Enhancing Pavement Sensor Data Harvesting for AI-Driven Transportation Studies 中文标题&#xff1a;为人工智能驱动的交通研究增强路面传感器数据采集 作者信息 Manish Kumar Krishne Gowda Purdue University, 465 Northwestern Avenue,…

unordered_set和unordered_map的使用

Hello&#xff0c;今天我来为大家介绍一下前几年才刚刚新出的两个容器——unordered_map和unordered_set&#xff0c;这两个容器属于是map系列和set系列中的一种&#xff0c;和map/set不同的是它们的底层&#xff0c;map/set的底层是红黑树&#xff0c;而unordered_map/unorder…

【实体类】分层设计

【实体类】分层设计 【一】实体类的PO、VO、DO、DAO、BO、DTO、POJO有什么区别【1】PO&#xff08;Persistent Object&#xff09;【2】VO&#xff08;View Object&#xff09;【3】DO&#xff08;Domain Object&#xff09;【4】DAO&#xff08;Data Access Object&#xff09…

【无人集群系列---无人机集群编队算法】

【无人集群系列---无人机集群编队算法】 一、核心目标二、主流编队控制方法1. 领航-跟随法&#xff08;Leader-Follower&#xff09;2. 虚拟结构法&#xff08;Virtual Structure&#xff09;3. 行为法&#xff08;Behavior-Based&#xff09;4. 人工势场法&#xff08;Artific…

C语言基本知识------指针(4)

1. 回调函数是什么&#xff1f; 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#xff0c;被调⽤的函数就是回调函数。 void qsort(void base,//指针…

使用 BFS 解决 最短路问题

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 1926.迷宫中离入口最近的出口 433.最小基因变化 127.单词接龙 675.为高尔夫比赛砍树 1926.迷宫中离入口最近的出口 题…

【嵌入式Linux应用开发基础】网络编程(1):TCP/IP协议栈

目录 一、TCP/IP协议栈分层与核心协议 2.1. 应用层 2.2. 传输层 2.3. 网络层 2.4. 链路层 二、嵌入式Socket编程关键步骤 2.1. TCP服务端流程 2.2. TCP客户端流程 三、TCP/IP协议栈的配置与调试 四、嵌入式场景优化策略 4.1. 资源管理 4.2. 性能调优 4.3. 健壮性保…

BUUCTF--[极客大挑战 2019]RCE ME

目录 URL编码取反绕过 异或绕过 异或的代码 flag 借助蚁剑中的插件进行绕过 利用动态链接库 编写恶意c语言代码 进行编译 然后再写一个php文件 将这两个文件上传到/var/tmp下 运行payload 直接看代码 <?php error_reporting(0); if(isset($_GET[code])){$code$_G…

【K8s】专题十六(2):Kubernetes 包管理工具之 Helm 使用

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…

VMware NSX 4.X Professional V2(2V0-41.24)题库2

What are two supported host switch modes? (Choose two.) A. Overlay Datapath B. Secure Datapath C. Standard Datapath D. Enhanced Datapath E. DPDK Datapath 答案&#xff1a;CD 完整题库见文章底部&#xff01; Which is an advantage of an L2 VPN in an NSX 4.x …

算法-数据结构-图的构建(邻接矩阵表示)

数据定义 //邻接矩阵表示图 //1.无向图是对称的 //2.有权的把a,到b 对应的位置换成权的值/*** 无向图* A B* A 0 1* B 1 0*/ /*** 有向图* A B* A 0 1* B 0 0*/import java.util.ArrayList; import java.util.List;/*** 带权图* A B* A 0 1* B 0 0*/ p…

ARCGIS国土超级工具集1.4更新说明

ARCGIS国土超级工具集V1.4版本&#xff0c;功能已增加至54 个。本次更新在V1.3版本的基础上&#xff0c;新增了“拓扑问题修复工具”并同时调整了数据处理工具栏的布局、工具操作界面的选择图层下拉框新增可选择位于图层组内的要素图层功能、数据保存路径新增了可选择数据库内的…

Ollama+Cherrystudio+beg-m3+Deepseek R1 32b部署本地私人知识库(2025年2月win11版)

之前综合网络各方面信息得到的配置表&#xff1a; 在信息爆炸的时代&#xff0c;数据安全和个性化需求愈发凸显。搭建本地私人知识库&#xff0c;不仅能确保数据的安全性&#xff0c;还能根据个人需求进行个性化定制&#xff0c;实现知识的高效管理和利用。随着技术的不断发展…