In brief, it's to help you avoid mistakes. Suppose for the moment that you could assign an object to a non-const reference of another type, as in:
// DISCLAIMER: bad code; does not compile
int a = 10;
double &x = a;
x = 2.0;
What would this mean? The second line would mean that x
is an alias for a
, implying that changes to x
are reflected in a
. If you did not intend this implication, then a non-const
reference is not the right tool. (If there will be no changes to x
, use a const
reference. If changes are not supposed to be reflected in a
, use a copy instead of a reference.) So the third line should set the value of a
to 2
. However it cannot.
Implicit conversions are easily one-way. There might not be a reverse conversion. Sure, in this specific example, converting the floating point 2.0
to the integer 2
is not problematic, but this is a special case. When you look at more complicated scenarios, especially scenarios involving classes instead of fundamental types, the reverse conversion might not even makes sense. Modifying via the reference is not something the language can guarantee, so it is prohibited in all cases for consistency.
The implicit conversion involves making a temporary object. If you compile the line const double &x = a;
the compiler would do the same thing your code does: create a new float
object and have x
refer to this new object. In the compiler's version the float
object has no name, while in your code, it is called temp
. In your code, if you were to try to modify x
, the modifications would appear in temp
, but not in a
because they are different objects. The same with the compiler's version – if you were able to modify through the reference, you would be modifying the temporary, not the original object. This breaks the semantics of references.
The upshot is that if you think you need a non-const
reference to an object of a different type (one that requires a conversion), there is likely a problem with your logic. The compiler can identify this quickly and tell you that you are trying something that will not work the way you probably think it will. This is a pitfall with no known utility, so big orange cones are here to ward off the unwary. Don't waste time testing your executable, because a bug has already been identified.
The language rules allow the compiler to be helpful by pointing out this near-certain error at compile-time, saving you the trouble of debugging run-time symptoms.