Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting to std::list using reverse iterator changes the value of the original reverse iterator

Have searched the net a lot, but couldn't find the answer to the issue.

I am inserting a value to an std::list using its reverse_iterator. While the insertion occurs at the appropriate position as expected, what I noticed is that the value of the original reverse_iterator used for insertion changes. Also the value of a completely unrelated reverse_iterator too changes. I have been able to reproduce this in a simple example

#include <iostream>
#include <list>
#include <string>

int main()
{
    // Creating a list of values 1, 2, 4, 5
    std::list<int> myList;
    myList.push_back(1);
    myList.push_back(2);
    myList.push_back(4);
    myList.push_back(5);

    // Changing it to 1, 2, 3, 4, 5 by inserting 3
    std::list<int>::reverse_iterator revIter = myList.rbegin();
    while(2 != *revIter)
    {
        std::cout << *revIter << "\t";
        ++revIter;
    }

    std::cout << "\n" << "Reverse iterator now points to " << *revIter;
    // Creating a copy of the reverse Iter before inserting.
    std::list<int>::reverse_iterator newRevIter = revIter;
    myList.insert(revIter.base(), 3);

    // Checking the values of revIter and newRevIter 
    std::cout << "\n" << "Reverse Iterator now points to " << *revIter; // UNEXPECTED RESULT HERE
    std::cout << "\n" << "New Reverse Iterator now points to " << *newRevIter; // UNEXPRECTED RESULT HERE

    std::cout << "\n" << "Printing final list:" << "\n";
    for(std::list<int>::iterator iter = myList.begin(); myList.end() != iter; ++iter)
    {
        std::cout << *iter << "\t"; // Results are fine
    }

    return 0;
}

RESULT

5    4
Reverse iterator now points to 2
Reverse iterator now points to 3
New Reverse iterator now points to 3
Printing final list:
1    2    3    4    5

Is this expected behaviour. If so how can reverse iterator be used to insert items to a list (Or is it useless in this regard)?

like image 826
john_zac Avatar asked Nov 19 '13 13:11

john_zac


1 Answers

I would avoid using reverse iterators (in general, and in particular for anything other than a sequential transversal). Forward and reverse iterators work differently, in the case of a forward iterator into a list, the iterator tracks the node that you access through operator*, but in the reverse case the iterator tracks the next element in the list. The act of dereferencing a reverse iterator obtains the predecessor of the node referred by the iterator and extracts the value from that. Graphically (f is a forward iterator, r is a reverse iterator)

  f
1 2 4
    r

Both the forward iterator f and the reverse iterator r will yield 2 when dereferenced, but the node they track is different. When you insert using r you insert between 2 and 4, but the underlying iterator is left pointing to the node holding the 4:

  f
1 2 3 4
      r

Now if you dereference r, the same process as above applies. The predecessor of the current node is obtained, and the value printed, except that now the predecessor of 4 is 3 and that is what you get.

Is this expected behaviour. If so how can reverse iterator be used to insert items to a list (Or is it useless in this regard)?

Yes, this is expected behavior. How can a reverse iterator be used to insert items to a list? Understanding how it works.

like image 108
David Rodríguez - dribeas Avatar answered Sep 21 '22 12:09

David Rodríguez - dribeas