Article Directory
1. Classification of iterators
We open a container at random and look at the iterator-related interface. We can find that the iterators of containers that support iterators have the following types
- forward iterator
- const forward iterator
- reverse iterator
- const reverse iterator
2. The use of reverse iterators
For the forward iterator, we are already very familiar with it, and it has been implemented in the simulation implementation of the previous STL container. So now let's look at the reverse iterator
❗❗Characteristics of reverse iterators
✅The iteration order of the reverse iterator is opposite to that of the forward iterator
✅rbegin() is equivalent to end()
✅rend() is equivalent to begin()
✅Reverse iterator++ is equivalent to forward iterator –
So now, let's take a look at the difference between the use of reverse iterators and forward iterators
void Test1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
auto rit = v.rbegin();
while (rit != v.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
It can be seen that there is no difference between the use of reverse iterators and forward iterators, except that the order of iteration is different.
3. Simulation implementation of reverse iterator
For the implementation of the reverse iterator, let's refer to how it is implemented in the library
Note: The library referred to here is version 3.0 of SGI, which corresponds to the analysis of STL source code by Mr. Hou Jie
reverse_iterator
Here we take the implementation of the reverse iterator of list as an example. You can see that the implementation of the reverse iterator in the library is realized by instantiating the class. From the usage, it can be inferred that the implementation logic of the reverse_iterator class template is passed in. To instantiate different types of reverse iterators to the type of the iterator , here the reverse iterator can be understood as a container adapter .
Let's take a look at the implementation of the reverse_iterator class, which is in the header file stl_iterator
By observing the code in the library, I already have a general understanding of the simulation implementation of reverse iterators, but there is a new syntax: extraction , the author is on the way of learning, the current ability is difficult to understand the extraction, so this simulation implementation Instead of using the extraction method, use the same solution as the list iterator - the method of passing template parameters to solve the simulation implementation of [C++] list
So, we can get the framework of the reverse iterator class as follows
template<class Iterator, class Ref, class Ptr>//这里对参数的设计参考之前list迭代器的这几
class reverse_iterator
{
typedef reserve_iterator<Iterator, Ref, Ptr> Self;//这里类型实例化出来太长了,做一个重命名
public:
//......
private:
Iterator _it;
};
Implementation of member functions
Referring to the member functions of the list iterator class, the member functions we need to design are:
- dereference
- Prepended ++–
- -> operator
- != and ==
According to our understanding, it is easy to write the following member functions.
reverse_iterator(Iterator it)//构造函数
:_it(it)
{
}
Self& operator++()//前置++
{
--_it;
return *this;
}
Self operator++(int)//后置++
{
Self tmp = _it;
--_it;
return tmp;
}
Self& operator--()//前置--
{
++_it;
return *this;
}
Self operator--(int)//后置--
{
Self tmp = _it;
++_it;
return tmp;
}
Ref operator*()
{
return *this;
}
Ptr operator->()
{
return &(operator*());
}
bool operator!=(const Self& s) const
{
return _it != s._it;
}
bool operator==(const Self& s) const
{
return _it == s._it;
}
Next, compare it with the one in the library.
Eh? This is different from what we have achieved, why? "There are no secrets under the source code" , let's take a look at the implementation of the iterator interface in the list
Oh, I got it, it turns out that the implementation of rbegin in the list is constructed using end(), and end returns the next position of the last element
If we want to get the last element, we will call the rbegin() interface. At this time, if we want to get the last element, we must let rbegin first – point to the last element before dereferencing.
So finally got the following implementation for *, and the rest don't change
Of course, if you are willing to change the parameters passed by all containers to the reverse iterator, you can also implement it according to the above implementation.
Ref operator*()
{
Iterator tmp = _it;
return *(--tmp);
}
Finally, our complete code for implementing the cashback iterator class is as follows
namespace zht
{
template<class Iterator, class Ref, class Ptr>//这里对参数的设计参考之前list迭代器的这几
class reverse_iterator
{
typedef reserve_iterator<Iterator, Ref, Ptr> Self;//这里类型实例化出来太长了,做一个重命名
public:
reverse_iterator(Iterator it)//构造函数
:_it(it)
{
}
Self& operator++()//前置++
{
--_it;
return *this;
}
Self operator++(int)//后置++
{
Self tmp = _it;
--_it;
return tmp;
}
Self& operator--()//前置--
{
++_it;
return *this;
}
Self operator--(int)//后置--
{
Self tmp = _it;
++_it;
return tmp;
}
Ref operator*()
{
Iterator tmp = _it;
return *(--tmp);
}
Ptr operator->()
{
return &(operator*());
}
bool operator!=(const Self& s) const
{
return _it != s._it;
}
bool operator==(const Self& s) const
{
return _it == s._it;
}
private:
Iterator _it;
};
}
4. Reverse iterator implementation of list class
With the implementation of the above iterator class, we can now add the reverse iterator in the previously simulated list class by the way
typedef zht::reverse_iterator<iterator, T&, T*> reverse_iterator;//反向迭代器
typedef zht::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;//const反向迭代器
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
So far, the STL iterator has been fully implemented.