2011-12-17 3 views
1

私のクラスにLastQueryInfo lastQueryというオブジェクトがあります。このオブジェクトが変わる度に、それをhistoryというベクトルに加えます。要素をベクトルに追加するときに、オブジェクトのコピーが作成されることを知る方法を教えてください。

最初に、私がhistory.push_back(lastQuery)を実行したとき、私は何が起こるのか分からなかった。ベクターがオブジェクトのコピーを作るだろうか?またはそれを参照し続けるつもりですか?ですから、後でlastQueryを変更すると、履歴ベクトル内のすべてのオブジェクトが変更されることになります(それらが参照であると仮定します)?

いくつかのテストの後、history.push_back(lastQuery)が実際にオブジェクトのコピーを作成し、それをベクターに追加することがわかりました。しかし、どのようなテストをせずにそれを知ることができますか? C++がいつコピーを作成するのか、それが実際のオブジェクトを追加するのかを私はどのように知ることができますか?常に

答えて

7

std::vector店コピー何でもpush_back()。したがって、渡した値を変更しても、ベクトルに格納されている値には影響しません。これはJavaやC#のようなものではなく、Object o;が実際にオブジェクトへの参照であり、オブジェクトはガベージコレクタが来るまで存続し、オブジェクトへの最後の参照がなくなるとそれをピックアップします。 C++ではObject o;が実際のオブジェクトであり、スコープの最後には表示されません。

std::vectorあなただけpush_back()オブジェクトへの参照が格納されている場合ので、それはこのようなもののために全く役に立たないだろう。

std::vector<int> numbers; 
for(/* loop condition */) { 
    int number = GetUserInput(); 
    numbers.push_back(n); 
} 

numberは、ループの終わりに離れて行きますので、numbersは参照を保持するだろうstd::vectorが参照のみを格納して実装されていた場合には存在しないものに変更します。 std::vectorに実際に値が格納されている場合は、ループの後でも値にアクセスできます。 C++ 11†

move semanticsをサポートしていますので、あなたが戻ってプッシュしているものは、実際にすぐに離れて行くだろうという一時的なものであれば、それは代わりのベクトル記憶にオブジェクトの内部を移動ますコピー。 C++ 11のstd::move()を明示的に使用して、push_back()の間に移動を強制することもできます。しかし、ベクトルは他のすべての場合に値をコピーします。これは、ベクトルのパフォーマンスを最適化するための実装の詳細です。

4

push_backを使用すると、格納されているオブジェクトのコピーが常に作成されます。

あなたがC++ 11を使用している場合は、そのコピーを避けるためには二つの方法があります。

  • emplace方法
  • を使用するには、ベクター中に作成したオブジェクトを移動:vec.push_back(std::move(obj));

C++ 11を使用していない場合は、ベクトルタイプとしてポインタまたはboost::shared_ptrを使用することだけができます。

関連する問題