The
A&
must refer to type A object. The 2 is not A.
However, the compiler sees a function
A::A(int)
that it can use to convert the 2 into A. To create an A object from value 2.
In other words, the compiler implicitly converts your code into:
1 2
|
A& foo = A( 2 ); // error
const A& bar = A( 2 );
| |
On both lines an A object is created. It has no name. It is
temporary; destructs itself at the end of the statement.
On both lines you try to create a reference to
unnamed temporary object.
Where does the reference refers to
after the statement?
To already destructed, no longer existing object. That would be really bad, would it not?
Now we know why the compiler refuses to create the foo.
Why the bar? The bar is const. That is an exception to the rule. The lifetime of the temporary object is prolonged. The memory of the object lingers while the reference exists. It is just "read-only" via the const reference. Keeping a modifiable object alive would be more complex, but an immutable object is manageable.
Note: If you do add keyword
explicit
, then neither compiles:
1 2 3 4 5 6 7 8 9
|
struct A
{
explicit A( int x )
: y( x ) // this is member initialization list syntax
{
}
int y;
};
| |
With the explicit keyword the compiler cannot implicitly call the constructor
A::A(int)
.