List的模拟实现和实现中遇见的一些问题C++

1.迭代器和原生指针的区别

		void f()
		{
			Node* pnode = _head->_next;
			iterator it = _head->_next;

			*pnode;
			*it;

			++pnode;
			++it;
		}

Node*原生指针和一个迭代器对象,他们占用空间是一样大的,都是4byte并且存的值也是一样的。但是对他们使用运算符的意义和结果是不一样的。

2.拷贝构造,析构和赋值重载是否需要我们自己实现?

迭代器是借助节点的指针访问修改链表
节点属于链表,不属于迭代器,所以他不管释放
都不需要自己实现,默认生成的即可

原因分析:
你将一个迭代器去拷贝构造成另外一个迭代器,是需要浅拷贝还是深拷贝?
浅拷贝,所以就不需要。

3.list中的const的模拟实现

const对于我们的要求来说,只需要满足只读不写就可以了
他的一些常规操作和我们实现的普通类型是一样的

我们参考list的源代码,我们可以使用模板参数来进行实现
代码请见下面list实现

4.->的相关问题

	struct Date
	{
		int _year;
		int _month;
		int _day;

		Date(int year = 1, int month = 1, int day = 1)
			:_year(year)
			, _month(month)
			, _day(day)
		{}
	};

	void test_list2()
	{
		list<Date> lt;
		lt.push_back(Date(2022, 3, 12));
		lt.push_back(Date(2022, 3, 13));
		lt.push_back(Date(2022, 3, 14));

		list<Date>::iterator it = lt.begin();
		while (it != lt.end())
		{
		    //这样是可以直接使用的,我们不模拟实现->就可以直接使用
		    //cout << (*it)._year << "/" << (*it)._month << "/" << (*it)._day << endl;

            //但是如何实现?->  是我们的迭代器更像指针
			cout << it->_year << "/" << it->_month << "/" << it->_day << endl;
			++it;
		}
		cout << endl;
	}

先说结果,但是为什这样可以?

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

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

it->_year相当于 it.operator->()
返回的是Date*
Date* 访问_year 应该是it->->_year
但是这样写的话,运算符可读性太差
所以这里编译器进行了优化,省略了一个->
素有类型只要想重载->都是这样的,都会优化。省略一个->

5.insert和erase的迭代器失效问题

		// 这里insert以后,pos是否失效?不失效
		iterator 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;

			return iterator(newnode);
		}

		// 这里erase以后,pos是否失效?一定失效
		// 节点删除了,迭代器也就失效了
		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;

			return iterator(next);
		}

延伸:
vector的erase之后迭代器会不会失效?
vector她erase后,说不定空间会缩容,所以可能会失效

6.构造函数的一个问题

		list(size_t n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

当我们构造:

   // list<int> lt2(5, 1);   时?就会出现问题,因为:
		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

1 是int类型,int不能解引用

7.代码实现

reverse_iterator.h

#pragma once
 

 
namespace sakeww
{
	// 

	// Iterator是哪个容器的迭代器,reverse_iterator<Iterator>就可以
	// 适配出哪个容器的反向迭代器,复用的体现

	template <class Iterator, class Ref, class Ptr>
	class reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;

		//typedef typename Iterator::Ref Ref;
		//typedef typename Iterator::Ptr Ptr;
		//凡是要取一个模板的内嵌类型,就要加typename,
		//告诉编译器后面的是类型,先让他过,现在去找他的类型是找不到的
		//等着类模板实例化了再去找他的具体类型

	public:
		reverse_iterator(Iterator it)
			:_it(it)
		{}

		typename Iterator::reference operator*()
		{
			//我们理解的实现
			//return *_it;
			
			//源码实现
			Iterator prev = _it;
			return *--prev;
		}

		typename Iterator::pointer operator->()
		{
			return &operator*();
		}

		self& operator++()
		{
			--_it;
			return *this;
		}

		self& operator--()
		{
			++_it;
			return *this;
		}

		bool operator!= (const self& rit) const
		{
			return _it != rit._it;
		}
		

	private:
		Iterator _it;
	};
}

list.h(内含部分测试用例)


#include"reverse_iterator.h"
namespace sakeww
{
	template<class T>
	struct ListNode
	{
		ListNode* _next;
		ListNode* _prev;
		T _data;

		ListNode(const T& data = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(data)
		{}
	};

	template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_iterator<T, Ref, Ptr> self;


		typedef Ref reference;
		typedef Ptr pointer;

		//typedef __list_iterator
		Node* _node;

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


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

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

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

		// it++
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		// --it
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		// it--
		self operator--(int)
		{
			self tmp(*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 ListNode<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;

		typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
		typedef reverse_iterator<iterator, T&, T*> reverse_iterator;


		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		iterator begin()
		{
			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);
		}

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

		// list<Date> lt1(5, Date(2022, 3, 15));
        // list<int> lt2(5, 1);
		list(int n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		list(size_t n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		// lt2(lt1)
		list(const list<T>& lt)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;

			list<T> tmp(lt.begin(), lt.end());
			std::swap(_head, tmp._head);
		}

		// lt2 = lt1
		list<T>& operator=(list<T> lt)
		{
			std::swap(_head, lt._head);
			return *this;
		}

		//lt2(lt1)传统写法
		//	list(const list<T>& lt)
		//{
		//	_head = new Node();
		//	_head->_next = _head;
		//	_head->_prev = _head;

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

		 lt2 = lt1传统写法
		//list<T>& operator=(const list<T>& lt)
		//{
		//	if (this != &lt)
		//	{
		//		clear();
		//		for (auto e : lt)
		//		{
		//			push_back(e);
		//		}
		//	}

		//	return *this;
		//}


		~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

		void clear()
		{
			/*iterator it = begin();
			while (it != end())
			{
				iterator del = it++;
				delete del._node;
			}

			_head->_next = _head;
			_head->_prev = _head;*/
			iterator it = begin();
			while (it != end())
			{
				erase(it++);
			}
		}

		//头插
		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		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());
		}
		//头删
		void pop_front()
		{
			erase(begin());
		}

		// 这里insert以后,pos是否失效?不失效
		iterator 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;

			return iterator(newnode);
		}

		// 这里erase以后,pos是否失效?一定失效
		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;

			return iterator(next);
		}

	private:
		Node* _head;
	};

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

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

		//lt.f();

		// 访问修改容器
		list<int>::iterator it = lt.begin();
		while (it != lt.end())
		{
			*it *= 2; // 修改
			cout << *it << " ";
			++it;
		}
		cout << endl;	

		print_list(lt);
	}

	struct Date
	{
		int _year;
		int _month;
		int _day;

		Date(int year = 1, int month = 1, int day = 1)
			:_year(year)
			, _month(month)
			, _day(day)
		{}
	};

	void test2()
	{
		list<Date> lt;
		lt.push_back(Date(2022, 3, 12));
		lt.push_back(Date(2022, 3, 13));
		lt.push_back(Date(2022, 3, 14));

		list<Date>::iterator it = lt.begin();
		while (it != lt.end())
		{
			//cout << (*it)._year << "/" << (*it)._month << "/" << (*it)._day << endl;
			cout << it->_year << "/" << it->_month << "/" << it->_day << endl;

			++it;
		}
		cout << endl;
	}

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

		list<int> lt2(lt);
		for (auto e : lt2)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int> lt3;
		lt3.push_back(10);
		lt3.push_back(10);
		lt3.push_back(10);
		lt3.push_back(10);

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

	void test4()
	{
		list<Date> lt(5, Date(2022, 3, 15));
		for (auto e : lt)
		{
			cout << e._year << "/" << e._month << "/" << e._day << endl;
		}
		cout << endl;

		list<int> lt2(5, 1);
		for (auto e : lt2)
		{
			cout << e << " ";
		}
		cout << endl;
	}


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

		list<int>::iterator it = lt1.begin();
		while (it != lt1.end())
		{
			//*it *= 2; // 修改
			cout << *it << " ";
			++it;
		}
		cout << endl;

		list<int>::reverse_iterator rit = lt1.rbegin();
		while (rit != lt1.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;
	}
}
  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值