Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ iterator and reverse iterator

Tags:

c++

iterator

I'm writing an iterator (actually it is const_iterator for my current object, and I want also to create a reverse_const_iterator also.

I looked around, to see how to do this and I stumbled across this:

Notice however that when an iterator is reversed, the reversed version does not point to the same element in the range, but to the one preceding it. This is so, in order to arrange for the past-the-end element of a range: An iterator pointing to a past-the-end element in a range, when reversed, is changed to point to the last element (not past it) of the range (this would be the first element of the range if reversed). And if an iterator to the first element in a range is reversed, the reversed iterator points to the element before the first element (this would be the past-the-end element of the range if reversed).

Is this what happens from the users' perspective, or when you dereference a reverse_iterator does it not abstract this away by giving you the value/reference of the object you think it is pointing to? Is this just implementation detail?

My understanding was:

for(i = obj.rbegin(); i != obj.rend(); i++)

was equivalent to

for(i = obj.begin(); i != obj.end(); i++)

except in reverse. And so *i would go backward through the container in the first case, and go forward through the container in the second case. Is my instinct correct?

like image 778
Bingo Avatar asked Feb 27 '13 10:02

Bingo


1 Answers

You're right that it's an abstraction. The reverse iterator contains a normal iterator that points at the element after the object you would get if you dereferenced it. However, it's not merely an implementation detail. The std::reverse_iterator adapter provides a member function call base which returns the underlying iterator.

The standard defines std::reverse_iterator as an iterator adapter with the following relation to the iterator its adapting:

The fundamental relation between a reverse iterator and its corresponding iterator i is established by the identity: &*(reverse_iterator(i)) == &*(i - 1)

A common use for base is erasing an element from a container, which would be done like so:

it++;
lst.erase(it.base());

If you want to do this while iterating over the container in reverse, you would do:

it++;
std::list<int>::reverse_iterator(lst.erase(it.base()));
like image 92
Joseph Mansfield Avatar answered Sep 22 '22 23:09

Joseph Mansfield