0
点赞
收藏
分享

微信扫一扫

linux运维一天一个shell命令之tcpdump详解

kolibreath 2024-08-06 阅读 27


目录

一.了解项目及其功能

📌了解list官方标准

了解模拟实现list

📌了解更底层的list实现

二.list迭代器和vector迭代器的异同

📌迭代器的分类

🎏单向迭代器(Forward Iterator)

🎏双向迭代器(Bidirectional Iterator)

🎏随机迭代器(Random Access Iterator)

📌list和vector的底层实现差异对迭代器的影响

三.逐步实现项目功能模块及其逻辑详解

📌分析list的组成结构

📌实现list结点类模板

🎏构造list结点类成员变量

🎏实现list结点类构造函数

📌实现list迭代器类模板

🎏构造list迭代器类成员变量

🎏实现list迭代器类构造函数

🎏实现operator*重载函数

🎏实现前置operator++重载函数

🎏实现后置operator++重载函数

🎏实现前置operator--重载函数

🎏实现后置operator--重载函数

🎏实现operator!=重载函数

🎏实现operator==重载函数

🎏实现operator->重载函数

🎏实现const修饰的list迭代器类模板

📌实现list类模板

🎏构造list类成员变量

🎏实现list类empty_init()函数

🎏实现list类无参构造函数

🎏实现list类拷贝构造函数

🎏实现list类swap()函数

🎏实现list类operator=()函数

🎏实现list类clear()函数

🎏实现list类析构函数

🎏实现list类begin()函数

🌳实现普通list类的begin()函数

🌳实现const修饰list类的begin()函数

🎏实现list类end()函数

🌳实现普通list类的end()函数

🌳实现const修饰list类的end()函数

🎏实现list类insert()函数

🎏实现list类erase()函数

🎏实现list类push_front()函数

🎏实现list类pop_front()函数

🎏实现list类push_back()函数

🎏实现list类pop_back()函数

🎏实现list类size()函数

四.项目完整代码

test.cpp文件

  list.h 文件

结语


一.了解项目及其功能

📌了解list官方标准


了解模拟实现list


📌了解更底层的list实现


二.list迭代器和vector迭代器的异同

📌迭代器的分类

🎏单向迭代器(Forward Iterator)


🎏双向迭代器(Bidirectional Iterator)


🎏随机迭代器(Random Access Iterator)


📌list和vector的底层实现差异对迭代器的影响


三.逐步实现项目功能模块及其逻辑详解

        通过第一部分对项目功能的介绍,我们已经对list的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!



📌分析list的组成结构


📌实现list结点类模板

🎏构造list结点类成员变量


🎏实现list结点类构造函数


📌实现list迭代器类模板

🎏构造list迭代器类成员变量


🎏实现list迭代器类构造函数


🎏实现operator*重载函数


🎏实现前置operator++重载函数


🎏实现后置operator++重载函数


🎏实现前置operator--重载函数


🎏实现后置operator--重载函数


🎏实现operator!=重载函数


🎏实现operator==重载函数


🎏实现operator->重载函数


🎏实现const修饰的list迭代器类模板


📌实现list类模板

🎏构造list类成员变量


🎏实现list类empty_init()函数


🎏实现list类无参构造函数


🎏实现list类拷贝构造函数


🎏实现list类swap()函数


🎏实现list类operator=()函数


🎏实现list类clear()函数


🎏实现list类析构函数


🎏实现list类begin()函数

🌳实现普通list类的begin()函数

🌳实现const修饰list类的begin()函数

🎏实现list类end()函数

🌳实现普通list类的end()函数

🌳实现const修饰list类的end()函数

🎏实现list类insert()函数


🎏实现list类erase()函数


🎏实现list类push_front()函数


🎏实现list类pop_front()函数


🎏实现list类push_back()函数


🎏实现list类pop_back()函数


🎏实现list类size()函数


四.项目完整代码

test.cpp文件

//仅测试list功能用
#include"STL_List.h"

int main()
{
	mfc::test_list1();
	mfc::test_list2();

	return 0;
}

  list.h 文件

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

namespace mfc 
{
	template<class T>
	//链表的链和结点分装成两个类
	struct list_node //struct定义结点就直接是公有的,如果用class就要将其设为public
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T _val;

		list_node(const T& val = T())
			:_next(nullptr)
			,_prev(nullptr)
			,_val(val)
		{}
	};

	template<class T,class Ref,class Ptr>
	//迭代器的本质是通过自定义类型的封装,改变了类型的行为

	//内置类型的行为不符合我们的要求时,C++就可以用一个类来封装这个类型,然后自己定义这个类型的行为
	//这里的思路是,我们本身就想用结点的指针来做list的迭代器,但是因为list的结构原因
	//它的++ / -- / * / != 等操作得到的结果不是我们想要的
	//所以我们就把这个结点指针封装起来,重新定义它的++ / -- / * / != 等操作
	//使这些操作得到的结果是我们想要的
	struct __list_iterator
	{
		typedef list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> self;
		Node* _node;

		__list_iterator(Node* node)
			:_node(node)
		{}

		//const迭代器的设计
		Ref operator*()
		{
			return _node->_val;
		}

		Ptr operator->()
		{
			return &_node->_val;
		}


		//++前置
		self& operator++()
		{
			//更新一下*this的_node指针,然后再返回*this
			_node = _node->_next;
			return *this;
		}

		//后置++
		self operator++(int)
		{
			self tmp(*this);
			//更新一下*this的_node指针,然后再返回*this
			_node = _node->_next;
			return tmp;
		}


		//--前置
		self& operator--()
		{
			//更新一下*this的_node指针,然后再返回*this
			_node = _node->_prev;
			return *this;
		}

		//后置--
		self operator--(int)
		{
			self tmp(*this);
			//更新一下*this的_node指针,然后再返回*this
			_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;
	public:
		//因为iterator和const_iterator只有operator*和operator->的返回值不同
		//所以我们不如把operator*和operator->的返回值也设置成模板参数,
		//当是iterator的时候,返回值模板就是T&/T*
		//当是const_iterator的时候,返回值模板就是const T&/const T*
		//本质上iterator和const_iterator还是两个类,但是用模板可以简化一些
		typedef __list_iterator<T,T&,T*> iterator;
		typedef __list_iterator<T,const T&,const T*> const_iterator;
		
		iterator begin()
		{
			//因为迭代器的底层实现是Node*,所以这里直接返回Node*没问题
			//单参数的构造函数支持隐式类型转换
			//return _head->_next;
			//所以上下两种方式都可以
			return (iterator)_head->_next;
		}

		iterator end()
		{
			return (iterator)_head;
		}

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

		const_iterator end() const
		{
			return (const_iterator)_head;
		}

		void empty_init()
		{
			_head = new Node;
			_head->_prev = _head;
			_head->_next = _head;
		}


		list()
		{
			empty_init();
		}

		list(const list<T>& lt)
		{
			empty_init();

			for (auto& e : lt)
			{
				push_back(e);
			}
		}

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

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

		~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

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


		void push_front(const T& x)
		{
			insert(begin(), x);
		}
		void pop_front()
		{
			erase(begin());
		}

		void push_back(const T& x)
		{
			/*
			//找尾
			Node* tail = _head->_prev;
			Node* newnode = new Node(x);
			
			//链接
			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _head;
			_head->_prev = newnode;
			*/
			insert(end(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

		//pos位置之前插入
		iterator insert(iterator pos, const T& x)
		{
			//纪录下pos位置和pos的上一个位置
			Node* cur = pos._node;
			Node* prev = cur->_prev;

			//创建新结点
			Node* newnode = new Node(x);

			//将pos的上一个结点和新结点相互链接
			prev->_next = newnode;
			newnode->_prev = prev;

			//将新结点和pos结点相互链接
			cur->_prev = newnode;
			newnode->_next = cur;

			//返回新插入的结点的迭代器
			return newnode;
		}

		//删除pos位置的结点
		iterator erase(iterator pos)
		{
			//不能删哨兵位的头结点
			assert(pos != end());

			//纪录下pos位置, pos的上一个位置和下一个位置
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			//将pos的上一个位置和下一个位置相互链接
			prev->_next = next;
			next->_prev = prev;

			//删除pos位置结点
			delete cur;

			//返回pos位置的下一个结点的迭代器
			return next;
		}

		//size求法1:写函数
		//方法2:加一个成员变量_size.然后insert就++,erase就--,初始化记得附0
		size_t size()
		{
			size_t sz = 0;
			iterator it = begin();
			while (it != end())
			{
				++sz;
				++it;
			}
			return sz;
		}


	private:
		//写成list_node* _head;是错误的
		//因为有了类模板后,类名就不是类型了,只有类模板显示实例化出的类才是类型
		Node* _head;
	};

	//迭代器测试打印函数
	void Print(const list<int>& lt)
	{
		list<int>::const_iterator it = lt.begin();

		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}
	
	//测试函数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();//这个地方把begin()赋给it是拷贝构造
		//而iterator没有实现拷贝构造,则默认就是浅拷贝
		//没有出错的原因就是,这里本身就是应该浅拷贝
		//我把begin()赋值给it,本身就是希望it指向这个结点,而不是指向这个结点的拷贝
		//那么,多个指针指向一个结点没有崩溃的原因是,我们没有进行二次释放操作
		//一般来讲,指针的销毁都伴随着空间的销毁,但是迭代器并没有销毁链表结点的权力
		//所以我们不写迭代器的析构函数,迭代器的销毁不导致结点的释放,所以不会有二次释放的问题
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

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

		Print(lt);
	}

	//测试函数2
	void test_list2()
	{
		class Point {
		public:
			int x;
			int y;
			Point(int xCoord = 0, int yCoord = 0)
				: x(xCoord)
				, y(yCoord)
			{}
		};

		list<Point> lt;
		lt.push_back(Point(1, 1));
		lt.push_back(Point(2, 2));
		lt.push_back(Point(3, 3));
		lt.push_back(Point(4, 4));
		list<Point>::iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << it->x << "," << it->y << endl;
			cout << (*it).x << "," << (*it).y << endl;
			cout << endl;
			++it;
		}

	}
}

结语

希望这篇list的实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!


举报

相关推荐

0 条评论