2016-09-08 6 views
2

以下のコードでは、最初の電話mkme = mvme_rvT& operator=(const T&&)に発送されません。rvalue referenceでmoveを呼び出さなければならないのはなぜですか?

#include <iostream> 
#include <string> 
#include <vector> 

using namespace std; 
using T = vector<int>; 

int main() 
{ 
    T mvme(10, 1), mkme; 
    T&& mvme_rv = move(mvme); // rvalue ref? 
    mkme = mvme_rv;   // calls T& operator=(const T&)? 
    cout << mvme.empty();  // 0 
    mkme = move(mvme_rv);  // calls T& operator=(const T&&)? 
    cout << mvme.empty();  // 1 
} 
+3

'mvme_rv'の型は' T'の値を参照していますが、その変数にその変数を使用すると、左辺値に過ぎません。 – skypjack

+2

"rvalue reference"と "rvalue"を区別します。 –

+1

命名式は常にlvlauesです。rvalue参照は、rvaluesにバインドする参照であり、lvalue参照はlvalues(主に)にバインドする参照です。その意味で、右辺値参照は、これまで存在していなかった言語に汎用の左辺値から右辺値への変換を追加する新しい言語機能です。明らかに、 –

答えて

-3

このコード行:

mkme = mvme_rv; 

コピーであるため、コピー割付(T& operator=(const T&))を使用します。これについての重要なことは、両方のオブジェクトが後で使用できることと、正しく実装されていれば、2つの同一のオブジェクトを提供すべきです。一方

、コード行:

mkme = move(mvme_rv); 

は、移動割り当て(T& operator=(const T&&))です。慣習上、これはmvme_rvオブジェクトをゴミ箱に(または少なくともクリアして)mkmeを基本的にはmvme_rvとします。

効果的にT&&は、一時オブジェクト(別名xvalue)を意味します。 std::moveメソッドは、基本的にオブジェクトを一時的にキャストします(@ richard-Hodgesのクレジットへのクレジット)。これは移動割当メソッドで使用することができます。

だから最終的にはないmkme = mvme_rv派遣T& operator=(const T&&)にしない理由を、あなたの質問に答えるために:一時オブジェクト(別名xavalue)ではありませんmvme_rvためです。

xvaluesについて

より:http://en.cppreference.com/w/cpp/language/value_category

+0

"std :: moveオペレータは基本的に通常のオブジェクトを取って勇気を取り除く"いいえ、オペランドには影響しません。それはオペレータではありません。 – juanchopanza

5

skypjackが正しくコメントとして、その名前によってオブジェクトにアクセスすると、常に左辺値参照になります。

これは安全機能であり、あなたがそれを考えていると、あなたがそのことを嬉しく思うでしょう。

あなたが知っているように、std::moveは、単にl値参照をr値参照にキャストします。返されたr値参照を直ちに使用する場合(つまり、名前が付けられていない場合)、それはr値参照のままです。

これは、r値の使用は、move(x)が記載されているコード内のポイントにしかないことを意味します。コードリーダーの観点から、xの状態が未定義になった場所を簡単に確認できます。

ので:

1: auto x = make_x(); 
2: auto&& r = std::move(x); 
3: // lots of other stuff 
35: // ... 
54: // ... 
55: take_my_x(r); 

は動作しません。もしそうなら、コードを維持している誰かが、行1で定義されたxが、行2で参照される参照を介して行55上で未定義状態になることを見ている(そして覚えている)のが苦労するでしょう。

より明示的に:

1: auto x = make_x(); 
2: // 
3: // lots of other stuff 
35: // ... 
54: // ... 
55: take_my_x(std::move(x)); 
関連する問題