2016-10-11 7 views
0
#include <iostream> 
#include <string> 

using namespace std; 

string&& f(string&& rvf) 
{ 
    cout << rvf << endl; 

    return (string&&)rvf; 
    // in the return statement, how rvf has become an lvalue? 
    // because of this I had to typecast explicitly 
} 

string&& g() 
{ 
    return "xyz"; 
} 

int main() 
{ 
    string&& st = f("rvalue"); 

    cout << "f " << st << endl; 

    string&& st2 = g(); 

    cout << "g " << str2 << endl; 
    // why this line prints junk/crashes some times? 

    return 0; 
} 

一般的な質問は:これらの右辺値のリファレンスはどういう意味ですか?

我々は、通常の変数に右辺値を割り当て、コピーが行われていますか?右辺値が別の変数にどの程度正確に「移動」されていますか?

コピー後に何が発生しますか?それはすぐに破壊されるか、その範囲外になるか?

+0

通常、戻り値の型としてrvalue参照を使用する理由はありません。ちょうど価値によって戻ります。 –

答えて

2
// in the return statement, how rvf has become an lvalue? 

rvfのタイプはstd::stringに右辺値参照であるが、rvf自体が左辺値です。このように考えてみましょう。rvfは、あなたがアドレスを取ることができる名前付き変数です。あなたはそれが左辺値であることをかなり確信することができます。

// why this line prints junk/crashes some times? 

あなたはgで未定義の動作をしているので:

一時的 std::stringを構築
string&& g() 
{ 
    return "xyz"; 
} 

は、それへの参照を返します。それが左辺値であるか左辺値であるかにかかわらず、あなたがそれを読むとすぐに未定義のビヘイビアの穴を埋めるでしょう。

通常の変数にrvalueを代入すると、コピーはどのように行われますか?右辺値が別の変数にどの程度正確に「移動」されていますか?

これはクラスによって異なります。組み込み型の場合、移動はコピーと同じです。 intをどのように "動かす"か考えてみましょう。それは本当に意味をなさない。 std::vectorのようなクラスでは、本質的にポインタを内部の動的に割り当てられたバッファにコピーし、それをオリジナルのnullptrに設定します(それはとにかく可能な実装の1つです)。

コピー後には何が起こりますか?それはすぐに破壊されるか、その範囲外になるか?

また、クラスによって異なります。標準ライブラリクラスは、移動後に「有効だが不特定の状態」にあるため、クラス不変条件を満たしていますが、そこにある有用なものに頼るべきではありません。あなたは喜んで標準に準拠したクラスを書くことができます。このクラスは、定義されていない動作をすることなく移動した後でアクセスすることはできません。

関連する問題