Обратный итератор продвигается с помощью std :: set :: erase - PullRequest
0 голосов
/ 12 декабря 2018

Я пытаюсь стереть элемент, в который я только что прошел.Сначала я забыл сохранить возвращаемое значение s1.erase (... внутри цикла for, чтобы в конечном итоге установить условие выхода из цикла. Учитывая то, как работает код, я ожидал, что цикл будет продолжаться бесконечно. Но он работаетпросто так, как он изначально был предназначен для работы. Похоже, что std :: erase продвигает итератор и сохраняет значение в rit. Я не могу найти документацию, которая объясняет это поведение.

https://en.cppreference.com/w/cpp/container/set/erase говорит, что возвращаемый итератор должен быть сохранен. Все аргументы set :: erase передаются по значению, так как продвигается обратный итератор?

Как завершается этот цикл?

std::set<int> s1;
s1.insert(20);
s1.insert(30);
s1.insert(50);

auto rit = s1.rbegin();

for (; rit!= s1.rend();)
{
    std::cout << "rit is " << *rit << " size is " << s1.size() << std::endl;
    s1.erase(std::next(rit).base());
    std::cout << "rit after erase is " << *rit << std::endl;
}

Выход:

Рит - 50 Размер - 3

Рит после стирания - 30

Рит - 30 Размер - 2

Ритпосле стирания 20

ритм 20, размер 1

Ошибка сегментации

1 Ответ

0 голосов
/ 12 декабря 2018

Напомним, что reverse_iterator::base() всегда на один элемент за очевидным значением итератора.Например, после auto rit = s1.rbegin(), *rit возвращает последний элемент, а rit.base() == s1.end().

Другими словами, *rit == *prev(rit.base())

В вашем цикле изначально rit.base() == s1.end().Тогда std::next(rit).base() относится к последнему элементу;этот элемент стирается.В std::set удаление элемента только делает недействительными итераторы для этого элемента, но не для любых других.s1.end() все еще является действительным итератором, как и rit, с rit.base() по-прежнему равным s1.end().Поэтому на следующей итерации цикла вы снова стираете последний элемент и снова оставляете rit.base() == s1.end().И т. Д.

В какой-то момент последний элемент стирается, s1 становится пустым, а затем *rit демонстрирует неопределенное поведение.Напомним, что *rit == *prev(rit.base()), но предыдущего элемента больше нет.

...