4

私は

map<char,my_class*> mymap;

その内容は以下の通りです。

mymap[0]=('a', 0x1);
mymap[1]=('b',0x2);
mymap[3]=('c',0x3);
mymap[4]=('d',0x1);

ご覧のとおり、キー「a」と「d」の値は同じです。マップ内のポインターを削除するための for ループがあります。

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

0x1 を 2 回削除しようとしているため、クラッシュします。私はこれをやってみました

for ( it=mymap.begin() ; it != mymap.end(); it++ ){
  if(!it->second){
      delete it->second;
      it->second = NULL;
  }
}

これでもポインタを NULL に 2 回設定しようとするため、例外が発生します。マップで上記のように重複した値を削除する最良の方法は何ですか?

4

4 に答える 4

5

含むNPEの答えshared_ptrは良いです。ただし、実際のポインターを使用する必要がある場合は、おそらく次のようにします。

set<my_class*> values;
for (it=mymap.begin(); it != mymap.end(); it++)
{
  // insert.second will be false if the value is already in the set
  if (values.insert(it->second).second)
    delete it->second;
}

// Make sure you do something with mymap to ensure you don't double-delete later!
于 2012-12-18T10:18:20.750 に答える
4

私のアドバイスはshared_ptr<my_class>、あなたの地図にとどまり、問題を完全に回避することです.

それができない場合は、setすでに割り当てを解除したポインタの補助コンテナ (たとえば a) を保持する必要があります。次に、マップを反復処理しながら、そのコンテナーを調べて更新します。

于 2012-12-18T10:14:58.250 に答える
2

2 番目のエントリを重複させたくない場合は、最初から挿入しないことをお勧めします。これを行うために私が考えることができる最もクリーンな解決策は、Boost bimap を使用することです。ただし、この動作は、2 番目のエントリを挿入したユーザーを驚かせると思います。

別の方法として ( を使用できない場合shared_ptr)、マップを分解するときの最も簡単な解決策は、std::set<MyClass*>すべての要素で一時的なものを作成し、そこから削除することです。(std::set重複がないことを保証します)。

そして、私がそれに取り組んでいる間、2番目のソリューションが失敗する理由は、ポインターをnullに2回設定しているためではありません。それは何も悪いことではありません。これは、同じオブジェクトへの 2 つの異なるポインターがあるためです。最初のオブジェクトを null に設定しても、2 番目のオブジェクトは変更されないため、同じオブジェクトを 2 回削除しようとすることになります。

于 2012-12-18T11:09:48.890 に答える
0

インスタンスを保存するか、スマートポインターを使用すると、より簡単になります。Std::Map にはオブジェクトへの独自の内部ポインターがあり、オブジェクトへの他の誰かのハンドルに依存することで頭痛を軽減できます。Boostライブラリには、いくつかのスマートポインターが含まれています。侵入参照カウント スマートポインターを使用すると、オブジェクトがマップから削除されると、オブジェクトが自動的に破棄される可能性があります。

その後、erase 関数を使用してマップから値を削除できます。これにより、デストラクタ チェーンを呼び出した後にオブジェクトが削除されます (最後の参照の場合)。

于 2012-12-18T10:26:21.280 に答える