STL-list实现(注释详解)

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

namespace zzd
{
	template<class T>
	struct list_node
	{
		成员函数
		//构造函数
		list_node(const T& data = T())
			:_prev(nullptr)
			, _next(nullptr)
			, _data(data)
		{}
		//~__list_node()-->不用自己写。因为:编辑器生成的析构函数,对于内置类型不处理,
		//{}                                 但对于自定义类型的成员,会调用该它自己的析构函数。

		成员变量
		list_node<T>* _prev;
		list_node<T>* _next;
		T _data;
	};

	// 迭代器---> 用一个类去封装了节点的指针
	// iterator - <T,T&,T*>
	// const_iterator - <T, const T&, const T*>
	template<class T, class Ref, class Ptr>
	struct list_iterator
	{
		typedef list_node<T> Node;
		typedef list_iterator<T, Ref, Ptr> self;
		成员函数
		//构造函数
		list_iterator(Node* node)
			:it_pnode(node)
		{}
		//拷贝构造与赋值重载不需要自己写,默认生成就可以,因为迭代器指向的资源不属于它,故完成浅拷贝就可以了。
		//析构函数也不需要自己写因为list中只有一个 Node指针 的成员变量,无管理的资源
		
		//运算符重载
		//注:*和-> 都是想实现直接操作Node里的成员变量:T _data; 
		Ref operator*()
		{
			return it_pnode->_data;
		}
		// 注意:-> 的返回值类型是 T*
		Ptr operator->()
		{
			return &it_pnode->_data;
		}
		// ++it
		self& operator++()
		{
			it_pnode = it_pnode->_next;
			return *this;
		}
		// it++
		self operator++(int)
		{
			self tmp(*this);//拷贝构造,用户未写,编辑器自动生成默认构造 完成浅拷贝
			it_pnode = it_pnode->_next;
			return tmp;
		}
		// --it
		self& operator--()
		{
			it_pnode = it_pnode->_prev;
			return *this;
		}
		// it--
		self operator--(int)
		{
			self tmp(*this);
			it_pnode = it_pnode->_prev;
			return tmp;
		}

		bool operator==(const self& it)
		{
			return it_pnode == it.it_pnode;
		}

		bool operator!=(const self& it)
		{
			return it_pnode != it.it_pnode;
		}

		成员变量
		Node* it_pnode;
	};
	
	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;
		成员函数
		//默认构造
		list()
		{
			//带头双向循环
			list_phead = new Node;
			list_phead->_next = list_phead;
			list_phead->_prev = list_phead;
		}
		//迭代器区间构造
		template<class input_iterator>
		list(input_iterator first, input_iterator last)
		{
			list_phead = new Node;
			list_phead->_next = list_phead;
			list_phead->_prev = list_phead;

			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
		//拷贝构造
		// list<T> it2(it1)
		1、传统写法

		//list(const list<T>& it)//传引用
		//{
		//	//以下三步只要是构造函数就要写,因为要构造一个新的list,它的头结点要先初始化。
		//	list_phead = new Node;
		//	list_phead->_next = list_phead;
		//	list_phead->_prev = list_phead;
		//
		//	for (auto& e : it)
		//	{
		//		push_back(e);
		//	}
		//	范围for会变成:
		//	//iterator it = begin(); ---> 不用加list<T>::的类域指定
		//	//while (it != end())
		//	//{
		//	//	push_back(*it);
		//	//	it++;
		//	//}
		//}

		//2、现代写法
		list(const list<T>& it)//传引用
		{
			list_phead = new Node;
			list_phead->_next = list_phead;
			list_phead->_prev = list_phead;

			list tmp(it.begin(), it.end());//调用构造函数 构造一个list tmp
			std::swap(list_phead, tmp.list_phead);
		}

		//赋值重载 --- 现代写法
		//lt1 = lt2
		list<T> operator=(list<T> it)//lt用的是传值,调用了一次拷贝构造
		{
			std::swap(list_phead, it.list_phead);
			return *this;
			//最后lt析构时还会释放原来lt1中的资源	
		}

		//析构函数
		~list()
		{
			clear();
			delete(list_phead);//删除头结点
			list_phead = nullptr;
		}
		iterator begin()
		{
			return iterator(list_phead->_next);
		}
		iterator end()
		{
			return iterator(list_phead);
		}
		const_iterator begin() const //const修饰的类对象只能调用const修饰的成员函数
		{
			return const_iterator(list_phead->_next); //调用const修饰的成员函数则决定构造并返回的迭代器类型为const_iterator
		}
		const_iterator end() const//构造并返回的迭代器类型为const_iterator,则说明迭代器类模板参数为<T, const T&, const T*>
		{
			return const_iterator(list_phead); //迭代器类模板参数为<T, const T&, const T*>即迭代器类中:Ref, Ptr换成了T&, T*
		}
		// Ref, Ptr换成了T&, T*,即迭代器的*、->返回值用const修饰了,则*和->迭代器变成了只读。
		//且迭代器的其他运算符重载返回值为const_iterator
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos.it_pnode;
			Node* prev = cur->_prev;
			Node* new_node = new Node(x);

			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = cur;
			cur->_prev = new_node;
			//构造匿名对象
			//也可以--->return newnode;--->单参的构造函数支持隐式类型转换
			return iterator(new_node);//insert返回新插入元素的迭代器
		}

		void push_back(const T& x)
		{
			insert(end(), x);
		}
		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		iterator erase(iterator pos)
		{
			assert(pos != end());//头节点不能删

			Node* cur = pos.it_pnode;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			delete cur;//cur为Node*,这里会先对cur调用Node的析构函数,然后释放cur指向的空间。
			prev->_next = next;
			next->_prev = prev;
			return iterator(next);//erase返回被删除元素的后一个位置的迭代器
		}

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

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);//erase返回被删除元素的后一个位置的迭代器
			}
		}

		size_t size()
		{
			size_t i = 0;
			iterator it = begin();
			while (it != end())
			{
				i++;
				it++;
			}
			return i;
		}
		bool empty()
		{
			return begin() == end();
		}

	private:
		成员变量
		Node* list_phead;
	};

	void print(const list<int>& l)
	{
		for (auto e : l)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test1()
	{
		list<int> l;
		l.push_back(1);
		l.push_back(2);
		l.push_back(3);
		l.push_back(4);
		l.push_back(5);
		print(l);
		l.pop_back();
		print(l);
		//for (auto& e : l)
		//{
		//	cout << e << " ";
		//}
		//cout << endl;
		l.clear();
		print(l);
		l.push_back(1);
		l.push_back(2);
		l.push_back(3);
		l.push_back(4);
		list<int> l2(l);
		cout << "l2:";
		print(l2);
		list<int> l3;
		l3.push_back(1);
		l3 = l2;
		cout << "l3:";
		print(l3);
	}
}

int main()
{
	zzd::test1();
	return 0;
}

 

 求赞,知道你们不会给,就是走个流程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值