Ответ 1
Это связано с тем, что обратный итератор имеет немного другую логику ссылок, чем обычный итератор: он указывает на элемент, но при разыменовании он дает ссылку на предыдущий элемент.
Вы легко увидите это, если попробуете следующее:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = { 1, 2, 3, 4, 5, 6 };
auto i = find(begin(v), end(v), 3);
cout << *i << endl;
vector<int>::const_reverse_iterator ri(i);
cout << *ri << endl;
}
Выход должен быть:
3
2
Когда обратный итератор физически указывает на определенный элемент, он логически указывает на предшествующий ему элемент. Таким образом, обратный итератор, физически указывающий на элемент в коллекции с индексом i
, при разыменовании выводит (ссылку на) элемент с индексом i-1
:
i, *i
|
- 1 2 3 4 5 6 -
| |
*ri ri
Это причина, по которой возврат итератора на rend()
фактически указывает на первый элемент в коллекции, а не на первый элемент перед первым элементом. Поэтому удаление первого элемента делает его недействительным.
begin, *begin end, *end
| |
- 1 2 3 4 5 6 -
| | | |
*rend rend *rbegin rbegin
Это относится не только к спискам, но и ко всем коллекциям, которые предлагают двунаправленные итераторы.