简体   繁体   中英

non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *

int main(int argc, char const *argv[])
{    
   int *i;
   const int * &j = i;
}

This code gives the error error: non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *

But it's not clear to me why this is not allowed. I defined j to be a reference to a pointer to a constant int. So if I set it equal to i , aren't I saying that j is a reference of i and we are not allowed to modify the int pointed to by i through j ?

So if I set it equal to i, aren't I saying that j is a reference of i

That's what you're trying to say. But the type of i is incompatible, so that's something that cannot be said.

and we are not allowed to modify the int pointed to by i through j?

If you had a pointer to const, then you couldn't modify the pointed int. And you could refer to such pointer with j . But you haven't created such pointer.

A pointer to non-const is convertible to pointer to const however. But result of such conversion is an rvalue, so your reference to non-const cannot be bound to it. If you used a reference to const, it would extend the lifetime of the temporary result of the implicit conversion:

const int * const &j = i;

But the reference just adds unncecessary cofusion. Better give the converted pointer a name, rather than refer to a temprary object:

const int* j = i;

Why is the type of i not compatible?

Because the language rules say so.

Is this just the rule?

This is the rule (from latest standard draft):

Given types “cv1 T1” and “cv2 T2”, “cv1 T1” is reference-related to “cv2 T2” if T1 is similar ([conv.qual]) to T2, or T1 is a base class of T2. “cv1 T1” is reference-compatible with “cv2 T2” if a prvalue of type “pointer to cv2 T2” can be converted to the type “pointer to cv1 T1” via a standard conversion sequence ([conv]). In all cases where the reference-compatible relationship of two types is used to establish the validity of a reference binding and the standard conversion sequence would be ill-formed, a program that necessitates such a binding is ill-formed.

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

  • If the reference is an lvalue reference and the initializer expression

    • is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2”, or

    • has a class type (ie, T2 is a class type), where T1 is not reference-related to T2, and can be converted to an lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3”92 (this conversion is selected by enumerating the applicable conversion functions ([over.match.ref]) and choosing the best one through overload resolution),

then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).

  • Otherwise, if the reference is an lvalue reference to a type that is not const-qualified or is volatile-qualified, the program is ill-formed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM