【C++】反向迭代器的模拟实现

前言:

     前面几篇文章我们在模拟实现string,vector和list时都只模拟实现了迭代器,并未单独实现反向迭代器,其实作者在这里是留了一点小心思的。

目录

(一)反向迭代器传统写法

(二)反向迭代器的模拟实现(适配器模式)


(一)反向迭代器传统写法

    有了我们模拟实现正向迭代器的基础,反向迭代器的实现其实对于大家并不难。无非就是反向迭代器中的rbegin是正向中end,rend是begin,++操作是往前走一格,--是往后走等等。

    我们手撕一个大家这种固有思维的list的反向迭代器:

template<class T, class Ref, class Ptr>
	struct __list_reverse_iterator
	{
		typedef list_node<T> node;
		typedef __list_reverse_iterator<T, Ref, Ptr> self;
		node* _node;

		__list_reverse_iterator(node* n)
			:_node(n)
		{}

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

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

		self& operator++()
		{
			_node = _node->_prev;

			return *this;
		}

		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_prev;

			return tmp;
		}

		self& operator--()
		{
			_node = _node->_next;

			return *this;
		}

		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_next;

			return tmp;
		}

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

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


	template<class T>
	class list
	{
		typedef list_node<T> node;
	public:

		typedef __list_reverse_iterator<T, T&, T*> reverse_iterator;

		typedef __list_const_iterator<T> const_iterator;

		reverse_iterator rbegin()
		{
			return reverse_iterator(_head->_prev);
		}

		reverse_iterator rend()
		{
			return reverse_iterator(_head);
		}
		//......
	}

我们这里确实实现了反向迭代器,但这个反向迭代器只是针对list的反向迭代器,我们你能否在有了迭代器基础上统一版本实现呢?

(二)反向迭代器的模拟实现(适配器模式)

    我们回忆一下,vector和list迭代器的模拟实现并不相同,一个是直接使用指针,另一个是对原生指针的封装从而模拟指针的行为。再通俗一点来看,vector在存储上是连续的可以直接用指针模拟实现迭代器,list在存储上并不是连续的,所以我们需要封装然后再类中模拟实现指针的解引用*、自加++等行为,从而模拟实现迭代器

     如果我们想要模拟实现反向迭代器,我们是不是也要针对每一种容器都各写一个呢???

    作者在这里事先告诉大家——不用。所以作者在等前面几个常用容器讲完之后统一来模拟实现反向迭代器!

====================================================================

    大家跟随作者一起来思考:

反向迭代器的rbegin其实相当于是正向迭代器的end,而rend其实就是正向迭代器的begin,“++”操作相当于正向迭代器的“--”操作等等,我们可不可以认为反向迭代器其实是一种“特殊”的正向迭代器呢?

我们既然已经一一模拟实现了正向迭代器,那么利用已经实现的正向迭代器的操作我们可以统一实现反向迭代器呀。

下面我们来模拟实现:

我们把正向迭代器作为模板参数传过去给到_cur,这样反向迭代器就可以自动匹配容器了,这样反向迭代器就可以统一实现复用了:

reverse_iteraor.h:

namespace zc
{//List::iteraor
	//vector::iterator
	template<class Iterator,class Ref,class Ptr>
	class ReverseIterator
	{public:
		typedef ReverseIterator<Iterator, Ref, Ptr> Self;
		Iterator _cur;

		ReverseIterator(Iterator it)
		:
			_cur(it)
		{}


		Ref operator*()
		{
			Iterator tmp = _cur;
			--tmp;
			return *tmp;
		}

		Self& operator++()
		{
			--_cur;
			return *this;
		}

		Self& operator--()
		{
			++_cur;
			return *this;
		}

		bool operator!=(const Self& s)
		{
			return _cur != s._cur;
		}


	};

}

list.h:

template<class T>
	class list
	{
		typedef list_node<T> node;
	public:
		
		typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
		typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;

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

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

这里主要强调一种用一种方法实现所有情况的思想,大家可以多次阅读!

总结:

  • 这里的核心点:用到了适配器模式。
  • 只需要在其他容器中适配一下这个反向迭代器即可
  • 代码的复用性很强

祝您学业有成!

Guess you like

Origin blog.csdn.net/m0_67821824/article/details/130032872