Prefácio:
Nos artigos anteriores, ao simular a implementação de string, vetor e lista, apenas simulamos a implementação do iterador, e não implementamos o iterador reverso separadamente.Na verdade, o autor deixou um pouco de reflexão aqui.
Índice
(1) Maneira tradicional de escrever o iterador reverso
(2) Implementação de simulação do iterador reverso (modo adaptador)
(1) Maneira tradicional de escrever o iterador reverso
Com base em nossa implementação simulada de iteradores diretos, a implementação de iteradores reversos não é realmente difícil para todos. Nada mais é do que o rbegin no iterador reverso é o meio-termo avançado, rend é start, a operação ++ é avançar um espaço, -- é retroceder e assim por diante.
Vamos rasgar um iterador reverso da lista do pensamento inerente 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 fato, implementamos um iterador reverso aqui, mas esse iterador reverso é apenas um iterador reverso para a lista. Podemos implementá-lo em uma versão unificada com base no iterador?
(2) Implementação de simulação do iterador reverso (modo adaptador)
Lembremos que as implementações de simulação de iteradores de vetores e de listas são diferentes: uma é usar ponteiros diretamente e a outra é encapsular ponteiros brutos para simular o comportamento de ponteiros . De um ponto de vista mais popular, o vetor é contínuo no armazenamento e os iteradores podem ser simulados diretamente pelos ponteiros, enquanto a lista não é contínua no armazenamento; portanto, precisamos encapsular e simular a desreferenciação* e o autoincremento dos ponteiros na classe .+ e outros comportamentos, simulando assim a implementação de iteradores .
Se quisermos simular a implementação de iteradores reversos, temos que escrever um para cada container? ? ?
O autor está aqui para avisar com antecedência - não há necessidade . Portanto, o autor esperou que os poucos contêineres anteriores comumente usados terminassem e simulassem a implementação de iteradores reversos!
==================================================== ==================
Todos seguem o autor para pensarem juntos:
O rbegin do iterador reverso é, na verdade, equivalente ao fim do iterador direto, e o rend é, na verdade, o início do iterador direto. A operação "++" é equivalente à operação "--" do iterador direto etc. Podemos pensar que os iteradores reversos são, na verdade, um iterador avançado "especial"?
Agora que simulamos e implementamos os iteradores diretos um por um, podemos implementar os iteradores reversos uniformemente usando as operações dos iteradores diretos implementados.
Vamos simular a implementação abaixo:
Passamos o iterador direto como um parâmetro de modelo para _cur, para que o iterador reverso possa corresponder automaticamente ao contêiner, para que o iterador reverso possa ser reutilizado uniformemente:
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;
}
};
}
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());
}
//.......
}
Aqui a ênfase principal está na ideia de usar um método para perceber todas as situações, e você pode ler várias vezes!
Resumir:
- O ponto principal aqui: o modo adaptador é usado.
- Só precisa adaptar esse iterador reverso em outros containers
- O código é altamente reutilizável
Desejo sucesso em seus estudos!