Очевидно, что решение, которое возвращает base () - это 1 off. Следующее удостоверение верно для reverse_iterator:
&*(reverse_iterator(i)) == &*(i - 1)
Или, другими словами, reverse_iterator всегда является одним проходом обычного итератора, основой которого он является. Не знаю почему.
В GCC
Просто измените
// SEGFAULT HERE
setOfInts.erase( rev_iter.base());
до
// WORKS!
setOfInts.erase( --rev_iter.base());
Мне определенно любопытно, почему указанная выше идентичность имеет смысл.
В Visual Studio
Возвращаясь к работе и пробуя это в Visual Studio, я вижу, что вышеупомянутое решение не совсем работает. «NextIter» становится недействительным при стирании. Вместо этого вам нужно сохранить временное значение от стирания, чтобы получить следующий итератор, вместо того, чтобы хранить следующий элемент, как указано выше.
set<int>::iterator tempIter = setOfInts.erase(--rev_iter.base());
rev_iter = setOfInts.erase(tempIter);
Итак, окончательное решение
int main()
{
using namespace std;
set<int> setOfInts;
setOfInts.insert(1);
setOfInts.insert(2);
setOfInts.insert(3);
set<int>::reverse_iterator rev_iter = setOfInts.rbegin();
while ( rev_iter != setOfInts.rend())
{
// Find 3 and try to erase
if (*rev_iter == 3)
{
cout << "Erasing : " << *rev_iter;
set<int>::iterator tempIter = setOfInts.erase( --rev_iter.base());
rev_iter = set<int>::reverse_iterator(tempIter);
}
else
{
++rev_iter;
}
}
}
Обратите внимание, ассоциативные контейнеры не возвращают итератор от стирания. Так что это решение не будет работать для карты, мультикарты и т. Д.