2017-03-17 9 views
4

コードA:すべてのconst文字列を参照することをお勧めしますか?

string a = "Hello World"; 

for (int i=0; i<1000000; ++i) 
    const string b = a; 

コードB:私は別に2つのコードを実行し、CPU時間を測定した場合

string a = "Hello World"; 

for (int i=0; i<1000000; ++i) 
    const string &b = a; 

は、コードBは、コードAよりも約2.5倍速かった

charintfloat ...のようなプリミティブ型を除いて、私はそれをコピーするのではなくオリジナルを参照する方が速いことを学んだ。

ほとんどの場合、その違いはほとんど無視できますが、常にconst stringタイプ(および他の非プリミティブタイプ)を参照することをお勧めしますか?

+7

通常のガイドラインは次のとおりです。 'sizeof'が' sizeof(void *) 'よりも大きければ、常にconst参照を渡し、それ以外の場合はコピーを渡します。オブジェクトを変更する場合は、サイズに関係なく非const参照を渡します。 – DeiDei

+2

例外があります。たとえば、関数の引数のコピーを作成し、値渡しする場合は暗黙的に必要なコピーを作成し、操作を効率的に行うなどの操作を利用できます。 – jaggedSpire

+2

クラスはカスタムのコピーや代入演算子を(文字列のように)定義するかもしれないので、 'sizeof'は常にコピー時間の良い指標ではありません。 –

答えて

3

はい、一般的に、高価なオブジェクトをコピーするにはconst参照を使用する方が良いです。しかし、元のオブジェクトが期待していないときに変更されないように注意する必要があります。特に、元のオブジェクトが破壊されていないことを確認する必要があります。これは、未定義の動作につながります。それはあなたのおもちゃの例では問題ではありませんが、現実世界では大きな問題です。

const参照を使用する最も良い場所は、関数のパラメータです。 を知っていると、関数に渡されたオブジェクトは、関数内にある間は変更も破棄もできません。

2

考慮すべきことがいくつかあります。

  1. あなたの使用例です。コピーしたいのですか、観察したいですか?
  2. 型はディープコピーのセマンティクスを実行しますか(たとえば、コピーにダイナミックメモリを割り当てる)かどうか

あなたは単にオブジェクト観察したい場合:
のオブジェクトの型がコピーで動的メモリを割り当てた場合は、常にconst参照渡し。
タイプのsizeofsizeof(void*)より大きい場合は、const参照を渡します。
それ以外の場合は値渡しします。

あなたがオブジェクトをコピーしたい場合は、単に値渡し。

もちろん、奇妙なユースケースでは何か他のことが起こるかもしれませんが、これは私がよく見る一般的なガイドラインです。

移動のセマンティクスも考慮されますが、それは別の質問です。

+2

'std :: string'にはC++で文字列を観察するための' std :: string_view'があります。 – Rakete1111

+0

興味深いデータポイントは、 'sizeof(string_view)'は '2 * sizeof(void *)'についてですが、 'string_view'はC++ 17標準ライブラリの値渡しです。 –

+1

@BoPersson私は最近、 'libcxx'と' stdlibC++ 'の両方で' std :: any'の実装を見ていました。 'libcxx'では、' stdlibC++ ' - ' sizeof(void *) 'では' small * object 'を '3 * sizeof(void *)'とみなしています。私はこれがかなり興味深いとわかりました。また、値渡しの標準イテレータでも見つけることができます。プラットフォーム上の 'std :: deque'のようないくつかのコンテナには、サイズが32バイトのイテレータがあります。 – DeiDei

関連する問題