Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterator value differs from reverse iterator value after conversion

Tags:

c++

iterator

stl

I have the following code:

int main()
{
    vector<int> v;

    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    auto it = v.begin() + 3;

    cout << "Iterator: " << *it << endl;

    vector<int>::reverse_iterator revIt(it);

    cout << "Reverse iterator: " << *revIt << endl;

}

After running this code I get the following output:

Iterator: 3
Reverse iterator: 2

Could someone explain why the 2 values differ ?

like image 326
Adrian Avatar asked Dec 21 '25 04:12

Adrian


2 Answers

Reverse iterators 'correspond' to a base iterator with an offset of one element because of how rbegin() and rend() have to be represented using base iterators that are valid (end() and begin() respectively). For example, rend() cannot be represented by an interator that 'points' before the container's begin() iterator, although that's what it logically represents. So rend()'s 'base iterator' is begin(). Therefore, rbegin()'s base iterator becomes end(). A reverse iterator automatically adjusts for that offset when it is dereferenced (using the * or -> operators).

An old article by Scott Meyers explains the relationship in detail along with a nice picture:

Guideline 3: Understand How to Use a reverse_iterator’s Base iterator

Invoking the base member function on a reverse_iterator yields the “corresponding” iterator, but it’s not really clear what that means. As an example, take a look at this code, which puts the numbers 1-5 in a vector, sets a reverse_iterator to point to the 3, and sets an iterator to the reverse_iterator’s base:

vector<int> v;

// put 1-5 in the vector
for (int i = 1; i <= 5; ++i) {
  v.push_back(i);
}

// make ri point to the 3
vector<int>::reverse_iterator ri =
  find(v.rbegin(), v.rend(), 3);

// make i the same as ri's base
vector<int>::iterator i(ri.base());

After executing this code, things can be thought of as looking like this:

alt text

This picture is nice, displaying the characteristic offset of a reverse_iterator and its corresponding base iterator that mimics the offset of rbegin() and rend() with respect to begin() and end(), but it doesn’t tell you everything you need to know. In particular, it doesn’t explain how to use i to perform operations you’d like to perform on ri.

like image 196
Michael Burr Avatar answered Dec 22 '25 18:12

Michael Burr


Looks like the documentation says they do that to handle past-the-end elements, i.e. if you reverse an iterator that is past the end, the new reverse iterator points to the last element.

like image 43
WildCrustacean Avatar answered Dec 22 '25 18:12

WildCrustacean