Итерация по карте и удаление элемента, который был динамически выделен

Вот мой код:

void SurfaceManager::SurfaceManagerDelete()
{
for(map<string,SurfaceManager*>::iterator Iter = SurfaceList.begin(); Iter != SurfaceList.end(); ++Iter)
{
delete (*Iter).second;

(Iter) = SurfaceList.erase(Iter);
}

SurfaceList.clear();
}

Почему это вызывает несколько утечек памяти при сканировании с помощью VLD? Я знаю, что это как-то связано с тем, как я удаляю память из элемента именно этой строки «(Iter) = SurfaceList.erase (Iter);», однако я хотел бы знать, почему и как я должен правильно удалить элементы из списка.

1

Решение

Проблема в том, что ++ ++ Iter в цикле for. Это потому что

(Iter) = SurfaceList.erase(Iter);

уже обновляет Iter, чтобы указывать на элемент после стертого, как приращение.

Поэтому ++ Iter затем пропускает другой элемент, фактически вы удаляете все остальные элементы!

1

Другие решения

Вы должны позаботиться о том, чтобы работать с правильными итераторами. В вашем случае вы пропускаете один итератор из-за ++Iter в for цикл, и вы иногда будете в конечном итоге звонить ++ на конце итератор.

Обычно мутирующий ассоциативный контейнерный цикл выглядит так:

for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
if (delete_condition)
{
// other stuff, like "delete it->second;"m.erase(it++);
}
else
{
++it;
}
}

Кроме того, если вы утилизируете весь контейнер, не используйте erase совсем:

for (auto & p : m) { delete p.second; }

// or alternatively

for (auto it = m.begin(); it != m.end(); ++it) { delete it->second; }

m.clear();

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

1

По вопросам рекламы [email protected]