Идиома стирания-удаления: что происходит, когда удаляется возвратный итератор?
Я получил этот вопрос, когда я читал erase-remove idiom
(пункт 32) из книги Скотта Мейерса "Эффективный STL".
vector<int> v;
...
v.erase(remove(v.begin(), v.end(), 99), v.end());
remove
в основном возвращает "новый логический конец" и элементы исходного диапазона, которые начинаются с "нового логического конца" диапазона и продолжаются до тех пор, пока реальным концом диапазона не станут элементы, которые будут удалены из контейнера.
Звучит хорошо. Теперь позвольте мне задать мой вопрос:
В приведенном выше примере remove
может вернуться v.end()
если 99 не найден в vector v
, Это в основном проходит past-the-end-iterator
стереть метод.
- Что происходит, когда
past-the-end-iterator
передается вerase
метод? Стандарт говорит, что это UB? - Если это неопределенное поведение, то
erase-remove idiom
Пример в книге Скотта Мейера должен был выглядеть так:
vector<int> v;
...
vector<int>::iterator newEndIter = remove(v.begin(), v.end(), 99);
if(newEndIter != v.end() )
{
v.erase(newEndIter, v.end();
}
Есть идеи по этому поводу?
3 ответа
Стандарт C++ говорит, что erase(q1,q2)
member "стирает элементы в диапазоне [q1,q2)" (см. раздел 23.1.1). Поскольку диапазон исключает последний элемент,
v.erase(v.end(), v.end());
действует и ничего не стирает.
Я бы подумал v.erase(v.end(), v.end())
будет хорошо определен и ничего не сотрет.
Итератор
first
не должен быть разыменованным, еслиfirst==last
: стирание пустого диапазона - это запрет.