次のコードがあるとします。
class some_class{};
some_class some_function()
{
return some_class();
}
これはかなりうまく機能しているようで、戻り値を作成するためだけに変数を宣言する手間が省けます。しかし、私はこれをどんな種類のチュートリアルやリファレンスでも見たことがないと思います。これはコンパイラ固有のもの(ビジュアルC ++)ですか?それともこれは何か間違ったことをしていますか?
次のコードがあるとします。
class some_class{};
some_class some_function()
{
return some_class();
}
これはかなりうまく機能しているようで、戻り値を作成するためだけに変数を宣言する手間が省けます。しかし、私はこれをどんな種類のチュートリアルやリファレンスでも見たことがないと思います。これはコンパイラ固有のもの(ビジュアルC ++)ですか?それともこれは何か間違ったことをしていますか?
いいえ、これは完全に有効です。コンパイラーは実際に一時的なものを最適化できるため、これもより効率的です。
関数呼び出しからオブジェクトを返すことは「ファクトリ」デザインパターンであり、広く使用されています。
ただし、オブジェクトを返すか、オブジェクトへのポインタを返すかには注意が必要です。これらの前者は、コンストラクター/代入演算子をコピーする方法を紹介しますが、これは面倒な場合があります。
有効ですが、呼び出し方によってはパフォーマンスが理想的ではない場合があります。
例えば:
A a;
a = fn();
と
A a = fn();
同じではありません。
最初のケースでは、デフォルトのコンストラクターが呼び出され、次に代入演算子が呼び出され、一時変数を構築する必要があります。
2 番目のケースでは、コピー コンストラクターが使用されます。
十分にインテリジェントなコンパイラは、どのような最適化が可能かを解決します。ただし、コピー コンストラクターがユーザー提供の場合、コンパイラーが一時変数を最適化する方法がわかりません。コピー コンストラクターを呼び出す必要があり、そのためには別のインスタンスが必要です。
Rob Walker の例との違いは、Google で調べたい場合は Return Value Optimization (RVO) と呼ばれます。
ちなみに、オブジェクトが最も効率的な方法で返されるようにしたい場合は、shared_ptr を使用してヒープ上に (つまり new を介して) オブジェクトを作成し、代わりに shared_ptr を返します。ポインターが返され、参照が正しくカウントされます。
それは完全に合理的なC++です。
これは完全に正当な C++ であり、どのコンパイラもこれを受け入れる必要があります。何か間違ったことをしているかもしれないと思う理由は何ですか?
クラスがかなり軽量である場合は、これが最善の方法です。つまり、コピーを作成するのにそれほど費用がかからないということです。
ただし、この方法の副作用の 1 つは、一時オブジェクトが作成される可能性が高くなる傾向があることです。
確実にコピーされないようにしたいより重いクラス (たとえば、大きなビットマップ イメージ) については、そのようなものを参照パラメータとして渡し、それを埋めて、完全に確実にすることをお勧めします。一時オブジェクトは作成されません。
全体として、構文を単純化し、物事をより直接的にすると、式でより多くの一時オブジェクトが作成されるという副作用が発生する可能性があります。これは、より重いオブジェクトのインターフェイスを設計するときに留意する必要があることです。