[C++] Implementación de simulación del iterador inverso

Prefacio:

     En los artículos anteriores, al simular la implementación de cadenas, vectores y listas, solo simulamos la implementación del iterador y no implementamos el iterador inverso por separado. De hecho, el autor dejó un poco de reflexión aquí.

Tabla de contenido

(1) Forma tradicional de escribir iterador inverso

(2) Implementación de simulación del iterador inverso (modo de adaptador)


(1) Forma tradicional de escribir iterador inverso

    Con la base de nuestra implementación simulada de iteradores directos, la implementación de iteradores inversos en realidad no es difícil para todos. No es nada más que rbegin en el iterador inverso es el extremo medio hacia adelante, rend es begin, la operación ++ es avanzar un espacio, -- es retroceder, y así sucesivamente.

    Vamos a romper un iterador inverso de la lista del pensamiento inherente de todos:

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);
		}
		//......
	}

De hecho, hemos implementado un iterador inverso aquí, pero este iterador inverso es solo un iterador inverso para la lista. ¿Podemos implementarlo en una versión unificada basada en el iterador?

(2) Implementación de simulación del iterador inverso (modo de adaptador)

    Recordemos que las implementaciones de simulación de iteradores de vector y lista son diferentes. Una es usar punteros directamente y la otra es encapsular punteros sin procesar para simular el comportamiento de los punteros . Desde un punto de vista más popular, el almacenamiento del vector es continuo y los punteros pueden simular directamente los iteradores, mientras que el almacenamiento de la lista no es continuo, por lo que debemos encapsular y luego simular la desreferenciación* y el autoincremento de los punteros en la clase. .+ y otros comportamientos, simulando así la implementación de iteradores .

     Si queremos simular la implementación de iteradores inversos, ¿tenemos que escribir uno para cada contenedor? ? ?

    El autor está aquí para decírtelo por adelantado, no es necesario . ¡Así que el autor esperó a que los contenedores anteriores de uso común terminaran y simularan la implementación de iteradores inversos!

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

    Todos sigan al autor para pensar juntos:

El rbegin del iterador inverso es en realidad equivalente al final del iterador directo, y el rend es en realidad el comienzo del iterador directo. La operación "++" es equivalente a la operación "--" del iterador directo, etc. ¿Podemos pensar que los iteradores inversos son en realidad un iterador directo "especial"?

Ahora que hemos simulado e implementado los iteradores directos uno por uno, podemos implementar los iteradores inversos de manera uniforme usando las operaciones de los iteradores directos implementados.

Simulemos la implementación a continuación:

Pasamos el iterador directo como un parámetro de plantilla a _cur, de modo que el iterador inverso pueda coincidir automáticamente con el contenedor, de modo que el iterador inverso se pueda reutilizar uniformemente:

inversa_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;
		}


	};

}

lista.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());
		}
//.......
}

Aquí el énfasis principal está en la idea de usar un método para realizar todas las situaciones, ¡y puedes leerlo muchas veces!

Resumir:

  • El punto central aquí: se utiliza el modo adaptador.
  • Solo necesito adaptar este iterador inverso en otros contenedores
  • El código es altamente reutilizable.

¡Te deseo éxito en tus estudios!

Supongo que te gusta

Origin blog.csdn.net/m0_67821824/article/details/130032872
Recomendado
Clasificación