Delaying the returned link

Given:

int& foo(); // don't care what the reference is to int intVal; 

In the following two cases, the right side is the same function call

 int& intRef = foo(); intVal = foo(); // a reference is returned... a value is assigned. 

In the second case, how does the returned link "translate" to a value?

Is this done by the assignment operator for int?

+4
source share
3 answers

At the language level, there is no such thing as link dereferencing. Link implements the concept of lvalue. The variable and the link are basically the same thing. The only difference between a variable and a link is that the variable is bound to its location in the repository automatically by the compiler, while the link is usually associated with user action at runtime.

In your example, there is no conceptual difference between intRef and intVal . Both are int values. And at a conceptual level, both are accessible through the same mechanism. You can even think of all the variables in your program as links that were implicitly pre-bound to you by the compiler. This is basically what Bjarne Stroustrup means in TC ++ PL when it says (not verbatim) that links can be considered as just alternative names for existing variables.

The only moment when the difference between them is felt is when you create these objects and initialize them. Initializing a link is the act of linking it to some storage location. Initializing a variable is the act of copying the original value to an existing repository.

But as soon as the link is initialized, it acts like a regular variable: the act of reading / writing a link is the act of reading / writing the storage location to which it is attached. Taking the address of the link, it is evaluated at the address of the storage location to which it is attached. And so on.

It is no secret that in many cases a link is implemented internally as a hidden pointer, i.e. like an invisible pointer that is implicitly played out for you every time you access it. In such cases (when it is really implemented using the pointer), dereferencing occurs again at each access to it. So this is not an assignment operator that does this as you ask in your question. It is the fact that you mentioned the name of this link in your code, which leads to dereferencing the invisible pointer.

However, an object that implements an "alternative name for an existing variable" does not necessarily require storage for itself, that is, in a compiled language there is no need to represent anything tangible, such as a hidden pointer. This is why the language standard 8.3.2 states that "it is not specified whether the link requires storage."

+9
source

foo returns some reference to an object of type "int". We will not care where this "int" comes from, and we just assume that it exists.

The first line int& intRef = foo() creates an intRef , which also refers to the exact same object of type "int" referenced by the return value of foo .

In the second line, the value of intVal is replaced by the value of the object referenced by the returned link.


In response to your comments:

It seems you are very confused between pointers and links. Links are like aliases for an object. Executing a reference refers to the object to which it refers.

There is no such thing as dereferencing a link. You can only dereference pointers. Selection is the act of using the unary operator * to get the object that the point points to. For example, if you have int* p , you can do *p to get the object it points to. This is dereferencing p .

The only time you can do * in a link is the object it refers to is a pointer (or operator* overloads). In your case, since foo returns int& , we cannot dereference it. The expression *foo() simply will not compile. This is because the return value of foo is of type "int", which is not a pointer and does not overload operator* .

For all purposes and purposes, you can treat the link returned with foo as just the object to which it refers. The purpose of this intVal value intVal really no different from the purpose of x - intVal in the following code:

 int intVal; int x = 5; intVal = x; 

As I am sure you understand, intVal assigned the value x . This is defined simply by the standard:

In a simple assignment ( = ), the value of an expression replaces the value of the object referenced by the left operand.

No conversion should occur at all, because both sides of the operator are of the same type.

This is no different from your situation. You only have:

 intVal = some_ref_to_int; 

Where some_ref_to_int is the expression foo() . The fact that this is a link does not matter. intVal gets the value of the object indicated by the link.

+3
source

intVal is an assignment expression defined in 5.17 [exp.ass] in the standard. The grammar rules for an assignment expression are quite complex, depending on several other grammar rules, but basically you need a modifiable lvalue on the left side of the = operator and a prvalue expression on the right side.

When

 intVal = foo(); 

an expression on RHS is an lvalue of type int , so a conversion occurs with a conversion of lvalue-to-r ... this is barely a conversion, since the value does not change and does not make the type (except that for base types, cv qualifiers are deleted, therefore, if lvalue is of type const int , prvalue will be of type int ). [conv.lval] says

The value gl (3.10) of a non-function type without an array T can be converted to prvalue. [...] If T is a non-class type, the prvalue type is a cv-unqualified version of T Otherwise, the prvalue type is T [...] the value contained in the object specified by glvalue is the result of prvalue.

Thus, prvalue is of type int and has the same value as foo() , i.e. the same value as the variable from which the link is returned.

Assignment rules express:

In a simple assignment ( = ), the value of an expression replaces the value of the object referenced by the left operand.

Thus, the value of intVal will be replaced by the value of prvalue. Rules continue:

If the left operand is not of the class type, the expression is implicitly converted (section 4) to the cv-unqualified type of the left operand.

Since int not a type of class (and therefore does not have operator= overloaded, it just uses the built-in assignment operator), the assignment converts RHS to int , which is the type that it already has in your case.

Thus, the value of intVal set equal to the value of prvalue, which we called the value of the expression glvalue foo() , that is, the value of the variable bound to the link.

Note that the lvalue-to-rvalue conversion has nothing to do with the fact that RHS is a reference. The same thing happens here:

 int val = 0; intVal = val; 

val is an lvalue of type int , so it is converted to a prvalue of type int , and the value of intVal set to the value of this value.

Rules are expressed in terms of the expression โ€œcategory of valueโ€ (that is, an lvalue or rvalue), not this link or not. Any "dereferencing" of the required link is implicitly and invisibly performed by the compiler to implement the desired behavior.

+1
source

All Articles