Why do I need to use std::move in the initialization list of a move-constructor?

前端 未结 2 1558
小鲜肉
小鲜肉 2021-01-01 22:21

Let\'s say I have a (trivial) class, which is move-constructible and move-assignable but not copy-constructable or copy-assignable:

class movable
{
  public:         


        
相关标签:
2条回答
  • 2021-01-01 22:23

    How is value_(value) different from movable m1(movable(42))?

    A named rvalue reference is an lvalue (and will thus bind to the deleted copy ctor), while a temporary is, well, an rvalue (a prvalue to be specific).

    §5 [expr] p6

    [...] In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues [...]

    Aswell as from the example:

    A&& ar = static_cast<A&&>(a);
    

    The expression ar is an lvalue.

    The above quotes are from non-normative notes, but are an adequate explanation, since the rest of clause 5 goes and explains which expressions only create xvalues (aka, only the specified expressions and none else will create xvalues). See also here for an exhaustive list.

    † xvalues are one subgroup of rvalues, with prvalues being the other subgroup. See this question for an explanation.

    0 讨论(0)
  • 2021-01-01 22:28

    That's because value is a named variable, and thus an lvalue. The std::move is required to cast it back into an rvalue, so that it will cause move-constructor overload of T to match.

    To say it another way: An rvalue reference can bind to an rvalue, but it is not itself an rvalue. It's just a reference, and in an expression it is an lvalue. The only way to create from it an expression that is an rvalue is by casting.

    0 讨论(0)
提交回复
热议问题