I cannot initialize a non-const reference to type T1 from a开发者_运维技巧 convertible type T2. However, I can with a const reference.
long l;
const long long &const_ref = l; // fine
long long &ref = l; // error: invalid initialization of reference of
// type 'long long int&' from expression of type
// 'long int'
Most problems I encountered were related to r-values that cannot be assigned to a non-const reference. This is not the case here -- can someone explain? Thanks.
An integer promotion results in an rvalue. long
can be promoted to a long long
, and then it gets bound to a const reference. Just as if you had done:
typedef long long type;
const type& x = type(l); // temporary!
Contrarily an rvalue, as you know, cannot be bound to a non-const reference. (After all, there is no actual long long
to refer to.)
long long
is not necessarily sized equal to long
and may even use an entire different internal representation. Therefor you cannot bind a non-const reference to long
to an object of type long long
or the other way around. The Standard forbids it, and your compiler is correct to not allow it.
You can wonder the same way about the following code snippet:
long a = 0;
long long b = 0;
a = b; // works!
long *pa = 0;
long long *pb = pa;
The last initialization won't work. Just because a type is convertible to another one, doesn't mean another type that compounds one of them is convertible to a third type that compounds the other one. Likewise, for the following case
struct A { long i; };
struct B { long long i; };
A a;
B b = a; // fail!
In this case A
and B
each compound the type long
and long long
respectively, much like long&
and long long&
compound these types. However they won't be convertible into each other just because of that fact. Other rules happen to apply.
If the reference is to const, a temporary object is created that has the correct type, and the reference is then bound to that object.
I'm not a standards lawyer, but I think this is because long long
is wider than long
. A const reference is permitted because you won't be changing the value of l
. A regular reference might lead to an assignment that's too big for l
, so the compiler won't allow it.
Let's assume that it's possible :
long long &ref = l;
It means that later in the code you can change the value referenced by ref to the value that is bigger then long type can hold but ok for long long. Practically, it means that you overwrite extra bytes of memory which can be used by different variable with unpredictable results.
精彩评论