2016-05-24 5 views
4

誰かがstd::moveの私の理解を助けることができますか?std :: move()を使用してr値参照変数を作成するのに使用できますか。 [C++]

r値の参照が範囲外になる場合は、std::move演算子を使用して割り当てられていれば、その参照も範囲外になると考えました。それはなぜ以下のコードのケースではないのですか?

#include<iostream> 
using namespace std; 

int main() 
{ 
    string one = "1 - one"; 
    string two = "2 - two"; 
    { 
     //not as expected 
     string & lValRef = one; 
     string && rValRef = std::move(two); 
     string newS(rValRef); 
    } 
    cout << "one : " << one << endl; 
    cout << "two : " << two << endl; 
    { 
     //as expected 
     string temp(std::move(one)); 
     string tempAssignment; 
     tempAssignment = std::move(two); 
    } 
    cout << "one : " << one << endl; 
    cout << "two : " << two << endl; 
    return 0; 
} 

あなたはそれhereをいじることができます。

私はいつもstd::moveを使ってオブジェクトを「削除可能な状態」にしておくと考えました。だから私は最初に何かを印刷したことに驚いた。私が行ったように(rValRef ')& &のr値参照を作成するのに使用できますか? [私はstd::move()が必要に応じて私の 'rValRef'の周囲に必要となることを理解しています。]

以下は私がこれをより良く理解するのに役立つ自分のコードです。あなたが望むならそれで遊んでください:) Code here

#include <iostream> 
#include <vector> 
using namespace std; 

class SimpleClass { 
    friend ostream& operator<<(ostream & s,const SimpleClass & rhs); 
private: 
    vector<char> data; 
public: 
    SimpleClass(initializer_list<char> lst):data(lst.size()) { 
     copy(lst.begin(),lst.end(),data.begin()); 
    } 
    SimpleClass(size_t dim = 0):data(dim){}; 
    virtual ~SimpleClass() = default; 
    SimpleClass(const SimpleClass & rhs) = default; 
    SimpleClass & operator=(const SimpleClass & rhs) = default; 
    SimpleClass(SimpleClass && rhs):data(move(rhs.data)){}; 
    SimpleClass & operator=(SimpleClass && rhs){ 
     if (this != &rhs){ 
      this->data = move(rhs.data); 
      return *this; 
     } 
    } 
}; 
ostream& operator<<(ostream & s,const SimpleClass & rhs){ 
    for (size_t i = 0; i != rhs.data.size(); ++i) 
     s << rhs.data[i]; 

    return s; 
} 
int main() 
{ 
    SimpleClass one = {'o','n','e'}; 
    SimpleClass two = {'t','w','o'}; 
    { 
     SimpleClass & lValRef = one; 
     SimpleClass && rValRef = std::move(two); 
    } 
    cout << "one : " << one << endl; 
    cout << "two : " << two << endl; 
    { 
     SimpleClass temp(std::move(one)); 
     SimpleClass tempAssignment; 
     tempAssignment = std::move(two); 
    } 
    cout << "one : " << one << endl; 
    cout << "two : " << two << endl; 
    return 0; 
} 
+0

もしあなたの言葉があなたの提案通りに働いていれば、それは非常に使いにくいでしょう。あなたのようなコードは失敗し、避けるのは難しいでしょう。だから代わりに、言語はあなたが明示的に 'std :: move'を使用して、名前が無効なオブジェクトを参照するようにする必要があります。 –

+0

@DavidSchwartzうわー、あなたが周りを回って「崩壊する」(あるいはあなたが入れたい)「浮動小数点の参照」を持つことができれば、コードが失敗するということに必ずしも同意するわけではありません。あなたは望みます。失敗の意味を説明できますか?しかし、私は間違いなくC++が 'std :: move() 'をコードの一般的な可読性やデバッグなどのために明示的に指定する必要があることに感謝する必要があると思います。 – JasoonS

+1

' string a = b; a + = "。"; a + = b; '。どのような種類の 'std :: copy'や' std :: keep'をどこにでも置く必要がありますが、最後の使用は必要です。それはひどく悪いので、言語は最後の使用時に表示を要求するもう1つの決定をしました。 –

答えて

5

ここで理解されるべきことは、参照型が値カテゴリとは別の概念であることです。その2行目に

string && rValRef = std::move(two); 
string newS(rValRef); 

rValRefの種類はstd::stringに右辺値参照が、rValRefの値カテゴリは左辺値です。これについての良い経験則は、あなたが何かの住所を取ることができるならば、それはおそらく左利きです。 rValRefはアドレスを取ることができる名前付き変数です。左辺値も同様です。

あなたが実際にreferenceeから移動したい場合は、式が右の値カテゴリを持つように再びstd::moveを呼び出す必要があります(具体的には、std::moveは右辺値の一種であるはxValueを返す):

string newS(std::move(rValRef)); 
関連する問題