Удаление нескольких объектов из unordered_map c++

когда я прохожусь итератором по всему контейнеру и удаляю из него объекты соответствующие некоторому значению, то после этого я не могу пользоваться содержимым контейнера. (выводить данные, и т.д.)

struct obj
{
    int number, value;
};

unordered_map <int, obj> example;

 void delete_obj()
{

    for (auto&& elem : example)
    {
        if (elem.second.value == 0)
            example.erase(elem.first);
    }
}

 void add_obj(int number, int value)
{
    obj add;
    add.number = number;
    add.value = value;

    example.insert(make_pair(number, add));
}

void print_obj()
{
     for (auto&& elem : example)
        cout << elem.second.number << " " << elem.second.value << endl;
}

int main()
{
    add_obj(11, 0);
    add_obj(22, 1);
    add_obj(33, 1);
    add_obj(44, 0);
    add_obj(55, 1);

    print_obj();

    delete_obj();
    cout << endl;

    print_obj();

    return 0;
}

Ответы (2 шт):

Автор решения: KoVadim

Нельзя изменять размер контейнера, пока по нему бегут "новомодным" for. Точнее можно, но нужно очень хорошо понимать, как это выстрелит и куда.

К большому сожалению, remove_if не умеет работать с ассоциативными контейнерами... Но есть общепринятый паттерн удаления.

void delete_obj()
{
    for(auto it = begin(example); it != end(example);)
    {
        if (it->second.value == 0)
        {
            it = example.erase(it);
        }
        else
            ++it;
    }
}
→ Ссылка
Автор решения: Chorkov

Нельзя удалять элемент контейнера, если на этот элемент есть живой итератор (иначе использование этого итератора, приведет к неопределенному поведению).

for (auto&& elem : example) // Здесь неявно создаются итераторы для обходя элементов контейнера 
{
    if (elem.second.value == 0)
        example.erase(elem.first); // Здесь вы удаляете элемент, на который есть жувой итератор (используется в цикле).
}

Если у вас c++20, то можно удалить так:

std::erase_if( example, [](auto& pair){ return pair.second.value==0; } );
→ Ссылка