Удаление нескольких объектов из 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; } );