理解戻り値最適化および還元temporaries-C++
-
21-09-2019 - |
質問
をご検討ください三つの機能
std::string get_a_string()
{
return "hello";
}
std::string get_a_string1()
{
return std::string("hello");
}
std::string get_a_string2()
{
std::string str("hello");
return str;
}
- まRVO適用するすべてのケースはどうでしょうか。
- しても大丈夫で返却時のように上記のコードについて教えてください。であると考えているOKってお返しする、という発想がこれにより値が返るのではなく、参考にします。
意思い?
解決
は最適化が行われますRVO。 RVOは古い機能とほとんどのコンパイラがサポートしています。最後のケースはそうNRVO(名前付きRVO)と呼ばれています。それは、C ++の比較的新しい機能です。標準的には可能ですが、NRVO(だけでなく、RVO)の実装を必要としませんが、いくつかのコンパイラがサポートしてます。
あなたはスコット・マイヤーズ帳 のより効果的なの項目20にRVOについてもっと読むことができましたC ++。 35の新しいあなたのプログラムを改善する方法やデザインのを。
ここの約良い記事ですVisual C ++ 2005でNRVOます。
他のヒント
まず、それはあなたが何をしている値によって一時的に戻すために、完全に大丈夫です。これは、コピーされ、元の範囲を出て行くもののコピーはそうではないだろうし、安全に、呼び出し側で使用することができます。
第二に、すべての3例は、(あなたがとにかく第三の場合には、一時的にアクセスしていないので)実際には同一であり、コンパイラはさらにそれらのすべてのために同じコードを放出する可能性があります。したがって、それはすべての3つのケースでRVOを使用することができます。これは完全にコンパイラに依存されます。
すべての例が正しいです。彼らはすべて一時的に構築し、戻り値の型のコピーコンストラクタを適用します。何のコピーコンストラクタが存在しない場合は、必ずしも、コードが失敗します。
RVOは、ほとんどのコンパイラの下ですべての3つのケースに起こります。唯一の違いは、標準的にはそれを強制しない最後のものです。これは、あなたは、という名前の変数を持っているので。しかし、ほとんどのコンパイラは、スマート十分には後でという名前の変数が宣言され、それが適用される以下の変換は、RVOのためのより良いオッズはという名前の変数に適用する...まだそれにRVOを適用することがあります。
あなたが他のコードで見てきた可能性があるとして、ところで、参照を返すことはもちろん可能です。何をしてはならないことは、ローカルオブジェクトトンの参照を返すことです。
std::string& get_a_string2()
{
std::string str("hello");
return str; //error!
}
ご存知のように、は、コンパイル時にエラーが発生します。しかし、
std::string& get_a_string2(std::string& str)
{
// do something to str
return str; //OK
}
うまく動作します。この場合には、関連する一切の建設やコピー工事はありません。単に関数は引数への参照を返します。
によって異なりますので、おのコンパイラ-どのプラットフォームで参照すか?ベストするコンパイル、 非常に さまざまな運転条件に対してアプリにチェックをASMコンパイラを構築しています。
Yes"、"OKですが、いろい懸念;速?パッケージのコスメ。すでに現地派遣、const参照されるのを一時的に延長される。生涯の参照-実際に触って確かめてみましょう。(ハーブサタexaplinsこ こちらの 参照端のポストです。
IMOだほとんどないほうがよい信頼コンパイラ最適化コードです。が少ない場合、または必要について注意する必要はありこのようなもふもふをご堪能ください(低いレベルのコードは、がんとの交流をハードウェア登録).
int foo() { return 42; }
int main(int, char**)
{
const int &iRef = foo();
// iRef is valid at this point too!
}