c++reverse-iterator

Is a reverse iterator constructed from an iterator is its previous iterator?


On https://en.cppreference.com/w/cpp/iterator/reverse_iterator it is said:

std::reverse_iterator is an iterator adaptor that reverses the direction of a given iterator. In other words, when provided with a bidirectional iterator, std::reverse_iterator produces a new iterator that moves from the end to the beginning of the sequence defined by the underlying bidirectional iterator.

For a reverse iterator r constructed from an iterator i, the relationship &*r == &*(i-1) is always true (as long as r is dereferenceable); thus a reverse iterator constructed from a one-past-the-end iterator dereferences to the last element in a sequence.

So I've tried this code to understand more:

int main() {


    std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 }; // fibonacci series
    // deque has bi-directional iterators

    std::deque<int>::iterator offEnd = di.end(); // one-past the last element in di
    std::deque<int>::reverse_iterator r(offEnd); // constructing a reverse iterator from an iterator from deque<int> di

    std::cout << &offEnd << " : " /*<< *r */ << std::endl;
    std::cout << &(offEnd - 1) << " : " << *(offEnd - 1) << std::endl;
    std::cout << &*r << " : " << *r << std::endl;

}

The output:

0023FDAC :
0023FC9C : 13
0048C608 : 13

Why the iterators have the same value but on different addresses???!!!

Does this mean &*r == &*(i-1) is not correct?


Solution

  • The address are different because you have different objects. (offEnd - 1) and r are distinct objects. Since they are, they have different addresses. What you need to do is dereference the iterator, and then get that address. Doing that gives you

    int main()
    {
        std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 }; // fibonacci series
        // deque has bi-directional iterators
    
        std::deque<int>::iterator offEnd = di.end(); // one-past the last element in di
        std::deque<int>::reverse_iterator r(offEnd); // constructing a reverse iterator from an iterator from deque<int> di
    
        std::cout << &(*offEnd) << " : " /*<< *r */ << std::endl;
        std::cout << &(*(offEnd - 1)) << " : " << *(offEnd - 1) << std::endl;
        std::cout << &*r << " : " << *r << std::endl;
    }
    

    which outputs:

    0xed3c8c : 
    0xed3c88 : 13
    0xed3c88 : 13
    

    And as you can see the addresses are the same since the iterators point to the same element.


    Do note that

    &(*offEnd)
    

    is illegal and is undefined behavior. There is no object at end() so it is illegal to dereference the past the end iterator.