-->

Generally, is dereference pointer expression resul

2020-08-22 07:45发布

问题:

Deferencing pointer leads to using the value of the object indirectly. But I've never really understood what does the "using" means. I started to think the question until my compiler yield an error for the following code

int i = 0, *pi = &i;
decltype(*pi) c; // error: 'c' declared as reference but not initialized.

I looked at the error for a very long time and searched some questions I can only give out the following arguments. I don't know if they are correct or not.

Arguments 1:

1) *p is an expression that is not a variable (or non-variable expression)

2) dereferencing pointer expression yields a reference, we are in fact using a reference to access the value of the object

Arguments 2:

the dereferencing expression only for which decltype returns a reference, it is not a general case

Please points out any incorrectness or inaccurate descriptions of the above arguments.

回答1:

Dereferencing a pointer yields an lvalue expression of the pointed-to type designating the object or function pointed to. It does not yield a reference.* *pi is an lvalue of type int.

decltype (with an exception not relevant here) reports both an expression's type and its value category, the latter being encoded with reference types. Since *pi is an lvalue, it's encoded as an lvalue reference type, so decltype(*pi) is int &: int for the type, & for the value category.

Expressions never have reference type because any referenceness is adjusted away "prior to any further analysis".


* This isn't a merely technical distinction: per the direction of core issue 232 and core issue 453, there are valid dereference expressions you can write where binding its result to a reference would cause undefined behavior.



回答2:

To answer your title question: as T.C. answered too, no. Expressions never have reference type. Given an int a; int &b = a;, both the expression a and the expression b have type int, and both expressions are lvalues.

1) *p is an expression that is not a variable (or non-variable expression)

Correct.

2) dereferencing pointer expression yields a reference, we are in fact using a reference to access the value of the object

Dereferencing a pointer gives an lvalue, which decltype changes into an lvalue reference.

the dereferencing expression only for which decltype returns a reference, it is not a general case

I'm not entirely sure what you mean here. If you mean that when decltype doesn't produce a reference, having a declaration decltype(...) c; without an initialiser can be valid, then yes, indeed. If you mean that aside from dereferenced pointers, decltype never produces a reference type, then no. For instance,

int a;
decltype((a)) b; // not okay - decltype((a)) is int & because (a) is not the name of the
                 // variable, and the expression (a) is an lvalue
decltype(a) c;   // okay - decltype(a) is int because a is the name of the variable
decltype(+a) d;  // okay - decltype(+a) is int because the +a is a prvalue of type int


回答3:

As a matter of fact, standard says following in 8.5.2.1:

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T”, the type of the result is “T”.

So it is not the reference, but decltype() gives you something which actually has a representation in the C++ types system, and reference is the closest thing to it.