1

これが私のコードです:

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);」の要素からメモリを削除する方法と関係があることはわかっていますが、その理由と想定方法を知りたいと思います。リストから要素を適切に削除します。

4

2 に答える 2

1

正しいイテレータを操作するように注意する必要があります。あなたの場合、ループ内にあるために1つのイテレータをスキップ++Iterfor++おり、エンドイテレータを呼び出すことになります。

通常、変化する連想コンテナループは次のようになります。

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 ++では、オブジェクトを厳密にスコープして、必要最小限の時間だけ存続するようにします。新しいマップが必要な場合は、長持ちするものをクリアして再利用するのではなく、新しいものを作成します。)

于 2012-09-23T20:00:19.257 に答える
1

問題は、forループの++Iterです。それは

(Iter) = SurfaceList.erase(Iter);

すでにIterを更新して、増分のように、消去された要素の後の要素を指すようにします。

したがって、++ Iterは別の要素をスキップし、事実上、他のすべての要素を削除することになります。

于 2012-09-23T20:35:19.770 に答える