Выбор ответа Middle Контейнеры STL изнутри спрашивают часто обновлено
Удаление в цикле по итератору
Вопрос
Как правильно удалить из std::vector<int> v все чётные элементы в цикле по итераторам?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: for (auto it = v.begin(); it != v.end();) { if (it % 2 == 0) it = v.erase(it); else ++it; }. erase инвалидирует итератор на удалённый элемент и все после него, но возвращает итератор на следующий элемент.
Варианты ответа
for (auto it = v.begin(); it != v.end(); ++it) if (*it % 2 == 0) v.erase(it);for (int x : v) if (x % 2 == 0) v.erase(std::find(v.begin(), v.end(), x));for (auto it = v.begin(); it != v.end();) { if (*it % 2 == 0) it = v.erase(it); else ++it; }правильный ответ- Удалять в цикле нельзя ни в каком виде: только скопировать нечётные в новый вектор и обменять их
Разбор
erase инвалидирует итератор на удалённый элемент и все после него, но возвращает итератор на следующий элемент. Его и надо использовать. Ещё лучше одной строкой: std::erase_if(v, [](int x) { return x % 2 == 0; }); (C++20), это O(n) вместо O(n²).
- Во втором варианте после
eraseвыполняется++itпо недействительному итератору: UB. - В третьем range-for держит итераторы, которые инвалидирует
erase: UB. - Удалять можно, нужно правильно обновлять итератор.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.