Search code examples
c++c++11rvalue-reference

Why copy constructor is called instead of move constructor in my code?


I'm trying to understand a move constructor and rvalue reference. So I tried this code on https://www.onlinegdb.com/online_c++_compiler. But the result confuses me.

#include <iostream>
#include <type_traits>


class A {
public:
  A() { std::cout << "Constructed" << std::endl; }
  A(const A& )= delete;
  A(A&&) { std::cout << "Move Constructed" << std::endl; }
};

int
main ()
{
  A&& a = A();
  A b = a; // error: use of deleted function ‘A::A(const A&)’
  //A b = static_cast<decltype(a)>(a); // This works, WTF?
  std::cout << std::is_rvalue_reference<decltype(a)>::value << std::endl; // pretty sure a is rvalue reference.

  return 0;
}

Solution

  • You're confusing with types and value categories.

    (emphasis mine)

    Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.

    As a named variable, a is an lvalue.

    The following expressions are lvalue expressions:

    • the name of a variable, ...
    • ...

    Then for A b = a; the copy constructor is selected. As you've tried, static_cast<decltype(a)>(a); would convert it to an xvalue (which is rvalue); you can also use std::move.

    A b = std::move(a);
    

    The following expressions are xvalue expressions:

    • a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as std::move(x);
    • ...