Ответ 1
Идиоматический способ написать этот цикл:
for (auto i = list.begin(); i != list.end();) {
if (condition)
i = list.erase(i);
else
++i;
}
Вы можете сделать то же самое с set
, multiset
, map
или multimap
. Для этих контейнеров вы можете стереть элемент, не затрагивая действительность для любых итераторов для других элементов. Другие контейнеры, такие как vector
или deque
, не так добры. Для этих контейнеров только элементы перед стираемым итератором остаются нетронутыми. Это различие просто потому, что list
хранить элементы в отдельно выделенных узлах. Легко взять одну ссылку. vector
являются смежными, взятие одного элемента приводит к перемещению всех элементов после его возврата в одну позицию.
Ваша петля сломана, потому что вы удаляете элемент в i
при каком-либо заданном условии. i
уже не является допустимым итератором после этого вызова. Затем ваш цикл for
увеличивает i
, но i
недействителен. Возникает ад на земле. Это точная ситуация, поэтому erase
возвращает итератор в элемент после того, что было стерто... поэтому вы можете продолжить перемещение list
.
Вы также можете использовать list::remove_if
:
list.remove_if([](auto& i) { return i > 10; });
В лямбда верните true, если элемент нужно удалить. В этом примере он удалит все элементы, превышающие 10.