Вставка в std:: list с помощью обратного итератора изменяет значение исходного обратного итератора

много искали в сети, но не смогли найти ответ на этот вопрос.

я вставляю значение в список std::, используя его reverse_iterator. Хотя вставка происходит в соответствующей позиции, как и ожидалось, я заметил, что значение исходного reverse_iterator, используемого для вставки, изменяется. Также изменяется значение полностью несвязанного reverse_iterator. Я смог воспроизвести это в простом виде. пример

#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;
}

результат

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

это ожидаемое поведение. Если да, то как можно использовать обратный итератор для вставки элементов в список (или он бесполезен в этом отношении)?

2 ответов


Я бы избегал использования обратных итераторов (в целом, и в частности для чего-либо, кроме последовательной поперечной). Прямые и обратные итераторы работают по-разному, в случае прямого итератора в список итератор отслеживает узел, к которому вы обращаетесь через operator*, но в обратном случае итератор отслеживает следующий элемент в списке. Акт разыменования обратного итератора получает предшественник узла, на который ссылается итератор, и извлекает значение из что. Графически (f-прямой итератор, r-обратный итератор)

  f
1 2 4
    r

как прямой итератор f, так и обратный итератор r дадут 2 при разыменовании, но узел, который они отслеживают, отличается. При вставке с помощью r вы вставляете между 2 и 4, но базовый итератор слева указывает на узел, содержащий 4:

  f
1 2 3 4
      r

Теперь, если вы разыменовали r, применяется тот же процесс, что и выше. Получен предшественник текущего узла и значение распечатано, за исключением того, что теперь предшественник 4 равен 3, и это то, что вы получаете.

это ожидаемое поведение. Если да, то как можно использовать обратный итератор для вставки элементов в список (или он бесполезен в этом отношении)?

Да, это ожидаемое поведение. Как можно использовать обратный итератор для вставки элементов в список? Понимание того, как это работает.


инвариантом после вставки является std::reverse_iterator<>::base(), а не . Но,base() делает целевой предыдущие элементы по сравнению с reverse_iterator:

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

что меня немного беспокоит, так это то, что у меня было std::distance до begin() (или rend().base() ):

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

Я:

обратный итератор теперь указывает на 2-4-3

обратный итератор сейчас указывает на 3-4-3

или я ожидаю, что второй будет "3-4-4", поскольку элемент вставлен до base()...