2009-11-17 3 views
5

私はJosuttisの "Using Maps as Associative Array"(The C++ Standard Library - A Tutorial and Reference, 2nd Edition)を使い、スタックオーバーフローでUsing a std::map as an associative arrayを見つけました。今私は地図に挿入するときに呼び出されるコンストラクタに関する多くの質問があります。連想配列としてC++マップを使って理解する助けが必要です

class C 
{ 
public: 

    string s; 

    C() { cout << "default " << endl;} 

    C(const string& p) : s(p) 
    { cout << "one param" << endl;} 

    C(const C& obj) 
    { 
     if (this != &obj) 
     { 
     s = obj.s; 
     } 
     cout << "copy constr" << endl; 
    } 

    C& operator = (const C& obj) 
    { 
     if (this != &obj) 
     { 
      s = obj.s; 
     } 
     cout << "copy initializer" << endl; 
     return *this; 
    } 
}; 

int main() 
{ 
    map<int,C> map1; 
    C obj("test"); 

    cout << "Inserting using index" << endl; 
    map1[1] = obj; 

    cout << "Inserting using insert/pair" << endl; 
    map1.insert(make_pair(2,obj)); 
} 

このプログラムの出力は次のとおりです:

one param 
Inserting using index 
default 
copy constr 
copy constr 
copy initializer 
Inserting using insert/pair 
copy constr 
copy constr 
copy constr 
copy constr 

私は初期化すると仮定した。(そのために私をお許しください最高のコーディング手法を使用していない)。ここ

は私のサンプルプログラムですインデックスによるマップは、デフォルトのコンストラクタを呼び出して、代入演算子を続けて呼び出す必要があります。

しかし、map1[1] = objを実行すると、次の出力が作成されます。

Inserting using index 
default 
copy constr 
copy constr 
copy initializer 

初期化の理解に役立つ人がいますか?

+0

を作成します。 –

+0

実際、STLコンテナのオブジェクトよりもポインタを持つ方が良いことを理解しました。 – mithuna

+1

@mithuna:警告:オブジェクトの代わりにポインタを保存すると、生涯管理の問題が発生するため、オブジェクトを格納する方が良いと言えます。 * *によってパフォーマンスの問題が発生する場合は、コピーを最適化できるかどうかを確認する必要があります。次に、*できない場合は、オブジェクトの代わりにポインタを格納することを検討できます。その場合、Boost.PointerContainerライブラリ(http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html)に興味があるかもしれません。 ptr_map(http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_map.html)を参照してください。 –

答えて

7

あなたはSTDの仕様を読めば::マップ、それはオペレータが[](この場合)

(*((this->insert(make_pair(1,C()))).first)).second 

と同等であることを述べているので、これはすべてのコンストラクタはあなたが見る呼び出しを説明しています。まず、デフォルトのコンストラクタC()を呼び出します。次にmake_pairを呼び出して、Cオブジェクトをコピーします。 insertを呼び出します。これは、作成したペアオブジェクトのコピーを作成し、Cコピーコンストラクタを再度呼び出します。最後に、代入演算子を呼び出して、挿入したオブジェクトを代入するオブジェクトに設定します。実際

+0

素敵で簡潔です。 –

+0

私の答えと同じ、より良い! +1して削除した鉱山。 –

+0

素敵なレスポンス、スペックを再読み込みして、それは今やたくさんの意味を成し遂げました。 – mithuna

0

map[1];を実行するとどうなりますか?これには、標準ライブラリで使用されているmapの実装に応じて、内部コピーが含まれる場合があります。

2

ドン;知っています。 しかし、これは興味深いです:

#include <string> 
#include <map> 
#include <iostream> 
using namespace std; 

class C 
{ 
    public: 
     string s; 
     C() 
     { 
      cout << "default " << endl; 
     } 
     C(const string& p) 
     : s(p) 
     { 
      cout << "one param(" << s << ")" << endl; 
     } 
     C(const C& obj) 
      :s(obj.s) 
     { 
      cout << "copy constr(" << s << ")" <<endl; 
     } 
     C& operator = (const C& obj) 
     { 
      cout << "copy initializer\t" <<; 

      C copy(obj); 
      std::swap(s,copy.s); 

      return *this; 
     } 
}; 

int main() 
{ 
    map<int,C> map1; 
    cout << "Inserting using index" << endl; 
    map1[1] = C("Plop"); 
} 

デフォルトの1が作成され、周りにコピーされるように見えます。
それから、外部のものは、いったん設置されると、その上に取り付けられます。

Inserting using index 
default 
copy constr() 
copy constr() 
one param(Plop) 
copy initializer  copy constr(Plop) 
0

map1[1] = objは、あなたが自分にコピー建設のためにテストする必要がいけないpair最初

関連する問題