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

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

Я вставляю значение в список std :: list, используя его 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

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

6

Решение

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

  f
1 2 4
r

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

  f
1 2 3 4
r

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

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

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

4

Другие решения

Инвариант после вставки std::reverse_iterator<>::base(), не std::reverse_iterator<> сам. Но, 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()

0

По вопросам рекламы [email protected]