2010-11-24 13 views
10

私はintをキーとして値としてポインタを格納するunordered_mapを持っています。私は鍵の存在を確認する必要があります。キーが利用できない場合は、キーと値を挿入する必要があります。どちらが良いアプローチですか?unordered_mapに値を代入する際の基本的な質問

ありがとうございました。両方の一つで十分であろうマップにクエリを使用するため

unordered_map<int, classA*>testMap; 
classA* ptr = testMap[1]; 
if(ptr == NULL) 
    testMap[1] = new classA; 


OR 

unordered_map<int, classA*>::iterator it = testMap.find(1); 
if(it == testMap.end()) 
{ 
    testMap.insert(make_pair(1, new classA)); 
} 
+0

動的に作成された 'classA'インスタンスを' std :: shared_ptr': 'std :: unordered_map >'に保存することをお勧めします。 'std :: make_shared (... ctr params ...)'を使ってインスタンスを作成することができます。これにより、リソースリークの心配が軽減されます。 –

+0

第1のアプローチまたは第2のルックアップを回避するバリアントは、マップ内に有効なヌルポインタを持たないことを確実に言うことができれば、より良いかもしれません。しかし、あなたが前提条件を述べていないので、私は第二の安全なアプローチのために行くだろう。 findの代わりにcount()関数を使用したり、そのローカル変数を取り除いてコードをクリアすることができます。 –

答えて

6

どちらの方法が良いです。

より良い方法は、要素への参照を取得し、その参照がヌルポインタである場合、それに割り当てされる:

classA*& ptr = testMap[1]; 
if (ptr == 0) 
    ptr = new classA; 

マップに存在しない要素を照会すると、自動的にそれを挿入するので、これが機能します(デフォルトで構築され、したがってNULLポインタが挿入されます)、operator[]は、参照(その要素が新しく作成されているか、すでに存在しているか)を返します。

しかし、このメソッド(または最初のメソッド)と2番目のメソッドのセマンティクスが微妙に異なることに注意してください。2番目のメソッドは、キーがマップに存在しない場合にのみ要素を挿入します。私の方法(とあなたの最初の方法)は、実際にキーがすでに存在していてもその値がヌルポインタだった場合、新しい要素を作成します。

+4

そのキーが既に存在し、 'NULL'が有効な値であればどうなりますか? – Nate

+0

これは一般的には良い考えではありません。ポインタ以外のものを格納していた場合は、テストする適切なデフォルト値を持たないかもしれません。また、メモリ割り当てにはルックアップよりもはるかに時間がかかるので、ここでの効率は実際には問題にはなりません。 –

+0

@Nate:編集を参照してください。 ;-) –

0

私は、次の操作を行います:

typedef unordered_map<int, classA*>::iterator my_iterator; 
std::pair<my_iterator, my_iterator> range = testMap.equal_range(1); 
if (range.first == range.second) //element not in map 
{ 
    testMap.insert(range.first, new classA); 
} 

EDIT:これは無意味であることを指摘しlijieに感謝を。 equal_rangeunderoded_mapの値が見つからない場合は[end, end]のペアを返します。

+0

要素が 'unordered_map'にない場合、' equal_range 'によって返される両方のイテレータは 'end()'です。ですから、 'insert'ヒントが有用であるかどうかは疑問です。 (つまり、 'testMap.insert(testMap.end()、newA)'と等価です。これはどちらの場合でもエラーであり、ペアでなければなりません)。 – lijie

+0

はい、そうです、私は標準的な注文地図を考えていました、ごめんなさい。私はあなたがエラーによって何を意味するかわからない、underoder_mapは2つの引数、1つのイテレータと1つの値を取る挿入関数を持っています:http://msdn.microsoft.com/en-us/library/bb982322.aspx –

1

2番目の方が良い方法です。最初に、classA* ptr = testMap[1]を実行すると、デフォルト値のNULLでアイテムがハッシュに作成されます。

マップ値をポインタ以外の値(たとえば、vectorなど)に変更する場合は、テストする適切なデフォルト値がない可能性があります。また、今後はNULLがあなたのマップに有効な値かもしれないので、デフォルト値テストは無意味です。

+2

なぜdownvote? –

+0

私はdownvoteをしませんでしたが、私は別の理由で2番目のアプローチを言うでしょう:あなたは無効なエントリを決して作成していません。 –

0

私はそれらが同等であると確信しています。最初のケースで

エントリが既に存在しない場合は、への呼び出し:

classA* ptr = testMap[1]; 

は実際にあなたがしてif文の間に移入うマップで空の要素を作成します。

insertを呼び出すと、2番目のエントリはマップにエントリが追加されます。

だから私はそれがあなたに合ったスタイルになると思います!