List迭代器的模拟实现

List迭代器

迭代器就是像指针一样的东西,通过迭代器可以对容器进行访问,迭代器屏蔽了容器的底层实现细节。

在STL中list迭代器是一个双向带头循环的链表,因为底层结构是链表空间是不连续的,所有我们不能直接对节点的指针++,来得到下个节点的地址。这时我们就需要自定义一个类型,该类型可以实现迭代器的操作。

template
class __List_iterator
{
public:
	node* _node;
};

类的成员变量是一个节点的指针。

需要在类中对迭代器++或者–的操作,++就是说我们需要得到下个节点的迭代器,在这里呢,迭代器就是封装的节点的指针,所以++和–也就是对节点的指针进行操作,来得到前后个节点的指针。

template
class __List_iterator
{
public:
	node* _node;
	typedef ListNode node;
	typedef __List_iterator self;
public:
	self& operator++()
	{
		_node = _node->next;
		return *this;
	}

	self& operator--()
	{
		_node = _node->prev;
		return *this;
	}
};

当实现了迭代的++和–后,就可以通过迭代器进行加减啦,如果我们需要遍历容器此时还需要实现一个!=;也就是两个节点指针进行比较。

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

接下来实现*和->,通过*我们可以取出节点的数据,->返回的是当前节点数据的地址。

		T& operator*()
		{
			return _node->val;
		}

		T* operator->()
		{
			return &_node->val;
		}

到这里我们完成了迭代器的基本功能,那么现在就会有一个新的问题,如果现在是一个const类型对象,此时就需要调用const迭代器,const迭代器是不允许对数据进行修改的,在上面的代码中如果使用的是const对象调用*和->,都可以完成对数据的修改,这是不对的。

  • 现在有一种方案就是在创建一个类,这个类实现的const迭代器,这样写的话就会使代码存在大量的冗余。
  • 另一种方法就是在迭代器的模板中在添加两个模板参数,用来确定*和->返回的类型。
	template
	class __List_iterator
	{
	public:
		typedef ListNode node;
		typedef __List_iterator self;
	public:
		__List_iterator(node* x)
			:_node(x)
		{}

		bool operator!=(const self& it)const
		{
			return _node != it._node;
		}
		self& operator++()
		{
			_node = _node->next;
			return *this;
		}

		self& operator--()
		{
			_node = _node->prev;
			return *this;
		}
        
		Ref operator*()
		{
			return _node->val;
		}

		Ptr operator->()
		{
			return &_node->val;
		}
		node* _node;
	};

如果是一个const迭代器,那么Ref就是const T&,Ptr就是const T*,此时我们就可以通过一个类,来实现不同的迭代器返回不同类型的结果。
List迭代器的模拟实现_第1张图片

反向迭代器

反向迭代器我们直接复用正向迭代器就可以

template
	class __Reverse_iterator
	{
	public:
		typedef __Reverse_iterator reverse_iterator;
	public:

		__Reverse_iterator(const iterator& it)
			:_rit(it)
		{}

		Ref operator*()
		{
			iterator tmp = _rit;
			return *--tmp;
		}

		Ptr operator->()
		{
			return &operator*();
		}

		reverse_iterator& operator++()
		{
			--_rit;
			return *this;
		}
		reverse_iterator& operator--()
		{
			++_rit;
			return *this;
		}

		bool operator!=(const reverse_iterator& it)const
		{
			return  _rit != it._rit;
		}
	private:
		iterator _rit;
	};

我们让正向迭代器的begin做反向迭代器的end,正向的end做反向的begin
List迭代器的模拟实现_第2张图片

反向迭代器的++复用的就是正向的–,反向的–复用的是正向的++;

你可能感兴趣的:(c++,链表,list,模板方法模式)