I'm puzzled as to how this code compiles: (https://godbolt.org/z/hjY4ca4rr)
class A
{
public:
A() = default;
A(A &&other) = default;
int x = 0;
};
A f(A a)
{
a.x = 1;
return a;
}
int main()
{
f(A());
return 0;
}
In principle, returning a from f() means copying it to the call-site location, but an A is not copy-able. NRVO copy elision may kick in but:
Anyone cares to clarify?
As Jarod pointed out, it's not doing a copy, but a move, since the compiler knows the variable won't be used afterwards So it's using the A(A &&other) constructor To verify it, you can just print out something in the constructor
Also, if you want to disable copy, I recommend you to explicitly write it (and follow the rule of five).
That leads us to this code:
#include <iostream>
class A
{
public:
A() = default;
A(A &&other)
{
std::cout << "A(A&&)" << std::endl;
}
A(const A&other) = delete;
A& operator=(const A &other) = delete;
A& operator=(A &&other)
{
std::cout << "A& operator=(A &&)" << std::endl;
return *this;
}
~A() = default;
int x = 0;
};
A f(A a)
{
a.x = 1;
return a;
}
int main()
{
f(A());
return 0;
}
Output:
A(A&&)
So it is definitely calling the move constructor.