[C++] Implementation of reverse iterator

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

image-20230428145547611

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

image-20230428153340421

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

image-20230428153855446

reverse_iteratorHere 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

image-20230428155332091

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.

image-20230428161535430

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

image-20230428161800027

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

image-20230428162046763

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

image-20230428165042111

So far, the STL iterator has been fully implemented.

Guess you like

Origin blog.csdn.net/weixin_63249832/article/details/130430045