Why do I have to call move on an rvalue reference?

后端 未结 2 1037
天涯浪人
天涯浪人 2020-12-01 17:18

In the code below, why doesn\'t the first call mkme = mvme_rv dispatch to T& operator=(const T&&)?

#include 

        
相关标签:
2条回答
  • 2020-12-01 17:34

    This line of code:

    mkme = mvme_rv;
    

    is a copy and will thus use a copy assignment (T& operator=(const T&)). The key thing about this is BOTH objects can be used afterwards and should - if implemented correctly - provide two identical objects.

    By contrast, this line of code:

    mkme = move(mvme_rv);
    

    is a move assignment (T& operator=(const T&&)). By convention, this will trash the mvme_rv object (or at least clear it) and make mkme basically what mvme_rv was previously.

    Effectively T&& means a temporary object (aka xvalue) - something that will not last. The std::move method basically casts the object to a temporary (credit to @richard-Hodges for that wording). This can then be used in the move assignment method.

    So finally to answer you question of why doesn't mkme = mvme_rv dispatch to T& operator=(const T&&): it's because mvme_rv isn't a temporary object (aka xavalue).


    More about xvalues: http://en.cppreference.com/w/cpp/language/value_category

    0 讨论(0)
  • 2020-12-01 17:52

    As skypjack correctly comments, accessing an object through its name always results in an lvalue reference.

    This is a safety feature and if you think it through you will realise that you are glad of it.

    As you know, std::move simply casts an l-value reference to an r-value reference. If we use the returned r-value reference immediately (i.e. un-named) then it remains an r-value reference.

    This means that the use of the r-value can only be at the point in the code where move(x) is mentioned. From a code-reader's perspective, it's now easy to see where x's state became undefined.

    so:

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

    does not work. If it did, someone maintaining the code would have a hard time seeing (and remembering) that x (defined on line 1) enters an undefined state on line 55 through a reference taken on line 2.

    This is a good deal more explicit:

     1: auto x = make_x();
     2: //
     3: // lots of other stuff
    35: // ...
    54: // ...
    55: take_my_x(std::move(x));
    
    0 讨论(0)
提交回复
热议问题