Обратный итератор продвигается с помощью std::set::erase
Я пытаюсь стереть элемент, в который я только что прошел. Сначала я забыл сохранить возвращаемое значение 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 ответ
Напомним, что 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())
, но предыдущего элемента больше нет.