3

重複の可能性:
std::map からアイテムをフィルタリングする方法は?
最初から最後まで繰り返しながら、マップ要素で erase() を呼び出すとどうなりますか?

オブジェクトのマップがあり、それを繰り返し処理していくつかのエントリを削除したいと考えています。

typedef std::map<A,B> MapT;
MapT m;
MapT::iterator it;

for(it = m.begin(); it != m.end(); it++ ) {
    if( condition ) m.erase(it);
}

この方法でできますか?

4

2 に答える 2

8

イテレータの場合std::map、削除された要素への参照は無効になります [23.1.2/8]。コードが無効化された後にイテレータを使用すると、 Undefined Behaviorが発生します。この未定義の動作を回避するには、呼び出しで無効になる前に反復子をインクリメントする必要があります。erase()

以下を使用する必要があります。

for(it = m.begin(); it != m.end(); ) {
    if( condition )
        m.erase(it++);
    else
        ++it;
}

ここでは、次の要素を参照するようにit++インクリメントitしますが、元の値のコピーを生成することに注意してください。したがって、が呼び出さitれたときに削除される要素を参照しません。erase()

于 2012-05-09T17:08:19.353 に答える
2

であると仮定するMapTstd::map、イテレータは消去されると無効になります。これを(ループで)行う正しい方法eraseは、イテレータをキャッシュして、消去する前にインクリメントすることです。

MapT m;
MapT::iterator it;

for(it = m.begin(); it != m.end();)
{
    if(condition)
    {
       MapT::iterator tmp = it++;
       m.erase(tmp);
    }
    else
    {
       ++it;
    } 
}
于 2012-05-09T17:10:49.290 に答える