Стирание при повторном вызове std:: list - программирование
Подтвердить что ты не робот

Стирание при повторном вызове std:: list

Если я использую цикл iterator в цикле for, и я использую erase для текущей итерации итератора, цикл for должен продолжать нормально и обращаться к остальным элементам list?

Из того, что я прочитал, это должно быть так и является основной отличительной характеристикой list vs deque или vector. Для моих целей, queue может работать, но мне нужно это поведение.

Вот цикл, который я рассматриваю:

    std::list<Sequence>::iterator iterator;
    iterator=m_concurrents.begin();
    for (;iterator!=m_concurrents.end();++iterator){
        if (iterator->passes()){
            m_concurrents.erase(iterator);
        }
    }
4b9b3361

Ответ 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.

Ответ 2

for (auto i = list.begin(); i != list.end(); ++i) {
    if (condition) {
        list.erase(i);
        --i;
    }
}