循环访问映射并删除动态分配的元素

Iterating through a map and deleting an element that was dynamically allocated

本文关键字:动态分配 元素 删除 访问 映射 循环      更新时间:2023-10-16

这是我的代码:

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);",但是我想知道为什么,以及我应该如何正确删除元素从列表中。

问题是 for 循环中的 ++Iter。那是因为

(Iter) = SurfaceList.erase(Iter);

已经更新 Iter 以指向擦除后的元素,就像增量一样。

因此,++Iter 然后跳过另一个元素,实际上您最终会删除所有其他元素!

您必须注意在正确的迭代器上进行操作。在您的情况下,由于for循环中的++Iter,您跳过了一个迭代器,有时最终会在结束迭代器上调用++

通常的变异关联容器循环如下所示:

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++中,您会严格限定对象的范围,以便它们只在最短的必要时间内生存,当您需要新地图时,只需创建一个新地图,而不是清除并重复使用寿命太长的地图。