This code
#include <iostream>
struct A
{
A(int i) {std::cout << "int received\n";}
A(A& a) {std::cout << "ref received\n";}
};
int main()
{
int j = 5;
A a = j;
}
unexpectedly throws the following compiler error:
error: invalid initialization of non-const reference of type 'A&' from an rvalue of type 'A'
note: initializing argument 1 of 'A::A(A&)'
note: after user-defined conversion: A::A(int)
When I remove the second constructor overload A(A& a), everything works as expected. I suppose that the compiler mistakenly calls the second constructor instead of the first one.
Why does this happen?
How can I have a class with both a reference constructor and an rvalue constructor work in harmony?
I use GNU GCC.
Note: I also noticed something weird: Apparently, if I replace the line A a = j; with A a(j);, everything works as expected. This however is not satisfactory because it still doesn't work if I'm trying to initialize the object from a function argument (ex: calling void f(A a) with f(j)).
A a = j;performs copy initialization.Until C++17,
Class
Ahas a copy construtor taking lvalue-reference to non-const, which can't bind to the temporary converted fromint. Even the construction from the temporaryAmight be optimized the copy constructor has to be available.Making the copy constructor taking lvalue-reference to
const(or adding move constructor) would solve the issue.Since C++17 because of mandatory copy elision, the code would work fine.
LIVE
On the other hand,
A a(j);performs direct initialization,ais initialized fromjdirectly, copy constructor doesn't involve in.