Является ли обратный итератор, построенный из итератора, его предыдущим итератором? - PullRequest
4 голосов
/ 20 сентября 2019

На https://en.cppreference.com/w/cpp/iterator/reverse_iterator сказано:

std::reverse_iterator - это адаптер итератора, который меняет направление заданного итератора.Другими словами, когда обеспечивается двунаправленный итератор, std::reverse_iterator создает новый итератор, который перемещается от конца к началу последовательности, определенной базовым двунаправленным итератором.

Для созданного обратного итератора rиз итератора i отношение &*r == &*(i-1) всегда истинно (если r разыменовано);таким образом, обратный итератор, построенный из итератора «один за другим», разыменовывает последний элемент в последовательности.

Итак, я попробовал этот код, чтобы понять больше:

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;

}

Вывод:

0023FDAC :
0023FC9C : 13
0048C608 : 13

Почему итераторы имеют одинаковое значение, но по разным адресам ??? !!!

Означает ли это, что &*r == &*(i-1) не правильно?

Ответы [ 2 ]

10 голосов
/ 21 сентября 2019

Адрес отличается, потому что у вас разные объекты.(offEnd - 1) и r являются различными объектами.Поскольку они есть, у них разные адреса.Вам нужно разыменовать итератор, а затем получить этот адрес.Это дает вам

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

, который выводит:

0xed3c8c : 
0xed3c88 : 13
0xed3c88 : 13

И, как вы можете видеть, адреса одинаковы, поскольку итераторы указывают на один и тот же элемент.


Обратите внимание, что

&(*offEnd)

недопустимо и является неопределенным поведением.В end() нет объекта, поэтому разыменование прошлого итератора конца незаконно.

1 голос
/ 21 сентября 2019

Причина ясна, как вы можете видеть, когда запрашиваете адреса offEnd и offEnd-1, которые совпадают.Вы запрашиваете адрес итератора, и он остается прежним, если вы перемещаетесь внутри этого итератора с оператором -.

...