右辺値参照で返す方が効率的ですか?


回答:


246
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

これは、左辺値参照の場合と同様に、ぶら下がり参照を返します。関数が戻った後、一時オブジェクトは破棄されます。Beta_ab次のように値で返す必要があります

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

今、それは一時的に適切に移動しています Beta_abオブジェクトを関数の戻り値にいます。コンパイラーが可能な場合は、RVO(戻り値の最適化)を使用して、移動を完全に回避します。今、あなたは次のことができます

Beta_ab ab = others.toAB();

また、一時abオブジェクトをに構築して移動するか、RVOを実行して、移動またはコピーを完全に省略します。読むことをお勧めします問題と、(N)RVOがこれとどのように相互作用するかを説明するBoostCon09 Rvalue References 101


右辺値参照を返すケースは、他の場合には良い考えです。あなたが持っていると想像してくださいgetAB()ますが、多くの場合、一時的に起動する機能を。右辺値の一時値に対してconst左辺値参照を返すようにすることは最適ではありません。このように実装できます

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

はローカル自動でも一時的でもないmoveので、この場合はオプションではないことに注意してくださいab。現在、ref-qualifier &&は、2番目の関数が右辺値の一時変数で呼び出され、コピーではなく次の移動を行うことを示しています

Beta_ab ab = Beta().getAB();

51
戻り値の型がr値参照の場合、ぶら下がり参照の問題が自動的に解消されると私は常に想定していました。それが私に噛み付く前に、私はそれをまっすぐにしてくれてうれしい。スタック破壊バグは最悪です。
deft_code 2009

31
:)実際、右辺値参照は、左辺値参照と同様に「単なる参照」です。彼らは何もコピーまたは保存しません。
ヨハネスシャウブ-litb

9
メンバー関数のconst&qualifierは、単純なconstよりも何が優れていますか?
ガリネット2014

4
+1されているがリンクが壊れている:BoostCon09 Rvalue References 101
Siu Ching Pong -Asuka Kenji-

3
@galinetteこれらは参照修飾子です。
Malcolm、

2

それはでき少し異なる文脈で、例えば、より効率的です。

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

興味深い観察として、私のマシンでclang++ -O3は上記のコードに対して54命令を生成するのに対し、通常の62命令を生成しますstd::min。ただし、-O0これを使用すると、上記のコードでは518命令が生成され、通常の481命令が生成されますstd::min


私はあなたの答えに混乱しています。同様の(たぶん)バージョンを試しましたが失敗しました:ideone.com/4GyUbZ理由を説明していただけますか?
2018

一時オブジェクトの参照を使用して、for(:)割り当て解除されたオブジェクトを統合しました。修正:ideone.com/tQVOal
wonder.mice

3
この答えは実際に間違っていませんか?T、Tパラメータテンプレートの&&ありません r値の参照ではなく、普遍的参照、およびその場合のために、我々がすべき常にコールのstd ::前方<T>は、いないはstd ::動きます!言うまでもなく、この回答は上記のトップ投票のものと直接矛盾します。
xdavidliu

@xdavidliuこの回答は、rvalueで返す方が効率的な方法の考案された例です。 std::move()ポイントをより明確に示すための明示的なキャストとして使用されます。これは、プロジェクトにコピーアンドペーストするコードではありません。関数内に一時オブジェクトが作成されるため、トップ投票の回答と矛盾しません。ここで返されるオブジェクトは引数の1つです(一時オブジェクトは、作成されたポイントを(字句的に)含む完全式を評価する最後のステップとして破棄されます)。
wonder.mice

2
@ wonder.mice次にTをstd :: string;に置き換えてください。ここではテンプレートを使用する必要はまったくありません。T&&をr値の参照として使用すると、テンプレートやr値を初めて使用する人を不必要に混乱させるだけのひどいスタイルになります。
xdavidliu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.