0
点赞
收藏
分享

微信扫一扫

家居厨房安全无小事:可燃气体报警器探头校准检测重要性解析

_karen 2024-05-25 阅读 30
c++list

目录

一.list容器介绍

二.C++中list的基本组成

三.list容器相关接口的模拟实现 

1.push_back()

2.迭代器的begin()和end() 

 3.insert()

4.erase() 

5.pop_front()

6.pop_back()

7.size() 

8.empty()

9.析构~list()和清除数据clear()

10.拷贝构造

 11.赋值运算

四.模拟实现时所遇到的问题

1.实现链表的迭代器

(1)原生指针的正确使用

 2.自定义类型要想支持运算符重载需要自己写

3.const迭代器不能被修改

4.合并const类型迭代器和普通迭代器(模板的进阶使用) 


一.list容器介绍

二.C++中list的基本组成

namespace List
{
	template <class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;

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

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		//构造函数(哨兵位)
		list()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
	private:
		Node* _head;
        size_t _size;
	};
}

三.list容器相关接口的模拟实现 

1.push_back()

void push_back(const T& x)
{
		Node* newnode = new Node(x);
		Node* tail = _head->_prev;
			
		tail->_next = newnode;
		newnode->_prev = tail;
		newnode->_next = _head;
		_head->_prev = newnode;
}

2.迭代器的begin()和end() 

typedef ListIterator<T> iterator;
iterator begin()
{
	return iterator(_head->_next);
}
iterator end()
{
	return iterator(_head);
}

 3.insert()

	    //pos位置插入
		void insert(iterator pos, const T& val)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(val);
			Node* prev = cur->_prev;

			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
            _size++;
		}

4.erase() 

        //删除
		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;
			delete cur;
            _size--;
			return iterator(next);
		}

5.pop_front()

void pop_front()
{
	erase(begin());
}

6.pop_back()

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

7.size() 

size_t size() const
{
	return _size;
}

8.empty()

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

9.析构~list()和清除数据clear()

void clear()
{
	iterator it = begin();
	while (it != end())
	{
		it = erase(it);
	}
}
~list()
{
	clear();
	delete _head;
	_head = nullptr;
}

10.拷贝构造

        void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;
		}
		//拷贝构造
		list(list<T>& It)
		{
			empty_init();
			for (auto& e : It)//写&为了避免It是String等类进行拷贝构造
			{
				push_back(e);
			}
		}

 11.赋值运算

		void swap(list<T> It)
		{
			std::swap(_head, It.head);
			std::swap(_size, It.size);
		}
		//赋值运算  It1=It3
		list<T>& operator=(list<T> It)
		{
			swap(It);
			return *this;
		}

四.模拟实现时所遇到的问题

1.实现链表的迭代器

(1)原生指针的正确使用

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

这里和vecctor进行对比,vecor中指针T*是可以进行++操作的,而指针Node*无法进行++操作,原因为:链表的每一个节点的物理空间不是连续的。

其次,Node*进行解引用并不能得到我们想要的数据(比如1),得的的是一个Node结点。

我们称这样的指针T*为不符合我们需求的原生指针。

  • 解决方法 
  • 注意 :该迭代器类不需要写析构函数,因为该迭代器的本质是要访问我们链表中的节点。不可以在访问完成后对该链表进行释放。

 2.自定义类型要想支持运算符重载需要自己写

  • 代码 
struct A
	{
		int _a1;
		int _a2;

		A(int a1 = 0, int a2 = 0)
			:_a1(a1)
			, _a2(a2)
		{}
	};
	void test_list2()
	{
		list<A> lt;
		A aa1(1, 1);
		A aa2 = { 1, 1 };
		lt.push_back(aa1);
		lt.push_back(aa2);
		lt.push_back(A(2, 2));
		lt.push_back({ 3, 3 });
		lt.push_back({ 4, 4 });

		A* ptr = &aa1;
		(*ptr)._a1;
		ptr->_a1;

		list<A>::iterator it = lt.begin();
		while (it != lt.end())
		{
			cout <<*it << endl;  报错
			++it;
		}
		cout << endl;
	}
}

  •  解决方法

3.const迭代器不能被修改

  • 代码
iterator begin()
{
		return iterator(_head->_next);
}
iterator end()
{
		return iterator(_head);
}
const_iterator begin() const
{
		return iterator(_head->_next);
}
const_iterator end() const
{
		return iterator(_head);
}

 要同时写上不同版本迭代器和const版本迭代器,如果只写了const版本的迭代器会导致非const对象也可以调用const成员函数(权限缩小),造成本身不可以被修改的结果最终可以被修改。

  • 注意 

4.合并const类型迭代器和普通迭代器(模板的进阶使用) 

  • 代码 
template <class T,class Ref,class Ptr>//Ref引用,Ptr指针
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T,Ref,Ptr> Self;

		Node* _node;

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

		//解引用  *it
		Ref operator*()
		{
			return _node->_data;
		}
		//->
		Ptr operator ->()
		{
			return &_node->_data;
		}

		//前置++
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		//后置++
		Self operator++(int)
		{
			Self tmp(*this);

			_node = _node->_next;
			return tmp;
		}
		//前置--
		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		//后置--
		Self operator--(int)
		{
			Self tmp(*this);

			_node = _node->_prev;
			return tmp;
		}
		//比较两个迭代器是否相等
		bool operator!=(const Self& it)
		{
			return _node != it._node;
		}
	};

template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
	/*	typedef ListIterator<T> iterator;
		typedef ListIterator<T> const_iterator;*/

		typedef ListIterator<T,T&,T*> iterator;
		typedef ListIterator<T,const T&,const T*> const_iterator;

		iterator begin()
		{
			return iterator(_head->_next);
		}
		iterator end()
		{
			return iterator(_head);
		}
		 

		const_iterator begin() const
		{
			return iterator(_head->_next);
		}
		const_iterator end() const
		{
			return iterator(_head);
		}
     }
  • 图解 

举报

相关推荐

0 条评论