1


For the following code, I know that because I implement a copy constructor the default move is blocked by the compiler, what I don't understand is why the compiler choose the copy constructor, and not issuing an error?
Can a rvalue reference be the parameter for a reference function if no rvalue ref function exists?
If not, what do happens here?

#include <iostream>

using namespace std;

class A{
    public:

        A(){printf("constructor\n");}
        A(const A& a){printf("copy constructor");}
};

int main()
{ 
    A a;
    A b = std::move(a);
    return 1; 
}

The output is:

constructor
copy constructor

Thanks

JFMR
  • 23,265
  • 4
  • 52
  • 76
DsCpp
  • 2,259
  • 3
  • 18
  • 46

2 Answers2

3

The reason is that rvalue expressions can be bound to function parameters that are const lvalue references.


Also note that const rvalue expressions cannot be bound to rvalue references:

class A{
    public:    
        A(){printf("constructor\n");}
        A(const A& a){printf("copy constructor");}
        A(A&&) = default; // <-- has move ctor
}; 

int main()
{ 
    const A a; // <-- const!
    A b = std::move(a); // <-- copy not move!!!
    return 1; 
}

The code above still calls the copy constructor, even though there is a move constructor.

JFMR
  • 23,265
  • 4
  • 52
  • 76
2

std::move will take your named value and turn it into an rvalue expression, nothing more.

And, just like for any other rvalue, if it can't be moved, it'll be copied.

An rvalue of type T can be bound to a const T& just fine.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055