1. ホーム
  2. c++

[解決済み】C++では値で渡すのと定数参照で渡すのはどちらが良いのでしょうか?

2022-04-06 18:20:16

質問

C++では、値で渡すのと定数参照で渡すのとどちらが良いのでしょうか?

どっちがいいんだろう? 定数参照で渡すと、変数のコピーを作成しないので、プログラムのパフォーマンスが向上するはずだと理解しています。

どのように解決するのですか?

以前は、一般的に推奨されるベストプラクティスでした 1 に対して には const ref によるパスを使用します。 すべてのタイプ ただし、組み込み型 ( char , int , double など)、イテレータと関数オブジェクトの場合 (から派生したクラス)。 std::*_function ).

が存在する以前は特にそうでした。 移動セマンティクス . 理由は簡単で、値で渡すとオブジェクトのコピーを作らなければならず、非常に小さなオブジェクトを除いて、これは参照を渡すよりも常に高くつくからです。

C++11で、私たちは 移動セマンティクス . 簡単に言うと、移動セマンティクスは、場合によっては、オブジェクトをコピーせずに「値で」渡すことを許可しています。特に、渡すオブジェクトが .

それ自体、オブジェクトの移動は、少なくとも参照渡しと同じくらいコストがかかります。しかし、多くの場合、関数は内部的にオブジェクトをコピーすることになります。 所有権 引数の 2

このような状況では、次のような(単純化した)トレードオフが成立します。

  1. オブジェクトを参照渡しして、内部でコピーすればよい。
  2. オブジェクトを値で渡すことができる。

"値で渡す "場合でも、オブジェクトがrvalueでない限り、オブジェクトはコピーされます。rvalueの場合、代わりにオブジェクトを移動させることができます。そのため、2番目のケースは突然「コピーしてから移動」ではなく、「移動してから(潜在的に)もう一度移動」になっています。

適切な移動コンストラクタを実装しているラージオブジェクト(ベクトル、文字列など)の場合、2番目のケースは次のようになります。 大いに よりも効率的です。したがって、次のようにすることが推奨されます。 関数が引数の所有権を持ち、オブジェクトの型が効率的な移動をサポートしている場合は、値渡しを使用します。 .


歴史的なメモです。

実際、現代のコンパイラは、値による受け渡しが高価であることを把握し、可能であれば const ref を使用するように呼び出しを暗黙的に変換することができるはずです。

理論的には。 実際には、コンパイラは関数のバイナリインタフェースを壊さずにこれを変更できるとは限りません。いくつかの特殊なケース(関数がインライン化されている場合)では、コンパイラが関数内のアクションによってオリジナルのオブジェクトが変更されないことを理解できれば、コピーは実際にエライドされます。

しかし、一般的にはコンパイラはこれを判断できず、C++の移動セマンティックスの出現により、この最適化はあまり意味をなさなくなりました。


1 例:スコット・マイヤーズで。 エフェクティブ C++ .

2 これは特にオブジェクトのコンストラクタによく当てはまります。コンストラクタは引数を受け取り、それを内部に保存して構築されたオブジェクトの状態の一部とすることができます。