Pasting into std :: list using a reverse iterator changes the value of the original reverse iterator

Search the web a lot, but could not find the answer to the question.

I am inserting a value into std :: list using its reverse_iterator. Although the insertion takes place at the appropriate place, as expected, I noticed that the value of the original return_iterator used for the insertion is changing. The value of a completely unbound reverse_iterator also changes. I was 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 the expected behavior. If so, how can you flip the iterator to insert items into the list (or is it useless in this regard)?

+6
source share
2 answers

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

  f 1 2 4 r 

Both the forward iterator f and the reverse iterator r will return 2 when dereferencing, but the node trace is different. When you insert using r, you insert between 2 and 4, but the main iterator remains on the node pointer, holding 4:

  f 1 2 3 4 r 

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

Is this the expected behavior. If so, how can you flip the iterator to insert items into the list (or is it useless in this regard)?

Yes, this is the expected behavior. How to use a reverse iterator to insert items into a list? Understanding how it works.

+4
source

The invariant after insertion is std::reverse_iterator<>::base() , not std::reverse_iterator<> . But base() targets the previous elements compared to reverse_iterator :

http://en.cppreference.com/w/cpp/iterator/reverse_iterator

What bothers me a bit is when std::distance begin() (or rend().base() ):

  std::cout << "\n" << "Reverse Iterator now points to " << *revIter << "-" << *(revIter.base())<< "-" << std::distance(revIter.base(), myList.rend().base()); 

I have:

The reverse iterator now points to 2-4-3

The reverse iterator now points to 3-4-3

Or I expect the second to be "3-4-4", since the element is inserted before base() ...

0
source

Source: https://habr.com/ru/post/958396/


All Articles