С++ stl, что делает base() do

У меня такой код:

vector <int> v;
for (int i=0; i<5; i++)
        v.push_back(i);
v.erase(find(v.rbegin(), v.rend(),2).base());

Этот код удаляет первый элемент из вектора v после первого обнаружения 2 (в векторе остаются: 0 1 2 4). Что делает .base() здесь?

Ответ 1

base() преобразует обратный итератор в соответствующий имперский итератор. Однако, несмотря на свою простоту, это соответствие не так тривиально, как можно было бы.

Когда обратный итератор указывает на один элемент, он разыгрывает предыдущий, поэтому элемент, на который он физически указывает, и элемент, который он логически указывает, различны. На следующей диаграмме i - это прямой итератор, а ri - обратный итератор, построенный из i:

                             i, *i
                             |
    -      0     1     2     3     4     -
                       |     | 
                       *ri   ri

Итак, если ri логически указывает на элемент 2, он физически указывает на элемент 3. Поэтому при преобразовании в форвардный итератор результирующий итератор укажет на элемент 3, который будет удален в вашем примере.

Следующая небольшая программа демонстрирует описанное выше поведение:

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main(int argc, char *argv[])
{
    std::vector<int> v { 0, 1, 2, 3, 4 };
    auto i = find(begin(v), end(v), 2);

    std::cout << *i << std::endl; // PRINTS 2

    std::reverse_iterator<decltype(i)> ri(i);
    std::cout << *ri << std::endl; // PRINTS 1
}

Вот живой пример.

Ответ 2

base() возвращает базовый итератор базы.

Базовый итератор ссылается на элемент, который находится рядом с элементом на данный момент указывает reverse_iterator. То есть std::reverse_iterator(it).base() == std::next(it).

Подробнее о reverse_iterator здесь.

enter image description here