开发者

Cannot initialize non-const reference from convertible type

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜