Home > Software engineering >  Temporary initialization and Reference initialization
Temporary initialization and Reference initialization

Time:04-12

I am trying to understand how reference initialization. For example, let's look at a typical example.

double val = 4.55;
const int &ref = val;

I can think of 2 possibilities of what is happening in the above snippet.

Possibility 1

The usual explanation is given as follows:

Here a temporary(prvalue) of type int with value 4 is created and then the reference ref is bound to this temporary(prvalue) int object instead of binding to the variable val directly. This happens because the type of the variable val on the right hand side is double while on the left hand side we have a reference to int. But for binding a reference to a variable the types should match. Moreover, the lifetime of the temporary prvalue is extended.

Possibility 2

I think there is another possibility that could happen which is as follows:

Here a temporary(prvalue) of type int with value 4 is created. But since const int &ref expects a glvalue and currently we've a prvalue, the temporary materialization kicks in and so the prvalue is converted to an xvalue. Then the reference ref is bound to this materialized xvalue(since xvalue is also a glvalue) instead of binding to the variable val directly. This happens because the type of the variable val on the right hand side is double while on the left hand side we have a reference to int. But for binding a reference to a variable the types should match. Moreover, the lifetime of the materialized temporary xvalue is extended.

My questions are:

  1. Which of the above explanation is correct according to the C 11 standard. I am open to accept that none of the explanation above is correct in which case what is the correct explanation.
  2. Which of the above explanation is correct according to the C 17 standard. I am open to accept that none of the explanation above is correct in which case what is the correct explanation.
  3. I am also confused to whether a prvalue in the first step of both of the possibilities above, is actually a temporary object? Or the xvalue is the actual object. I mean do we have 2 temporary objects, like the first one due to "conversion to prvalue" and second one due to the "prvalue to xvalue" conversion(temporary materiliazation). Or do we only have one temporary which is due to the "prvalue to xvalue" temporary materialization.

PS: I am not looking for a way to solve this. For example, i know that i can simply write: const double &ref = val;. My aim is to understand what is happening according to C 11 and C 17 standards.

CodePudding user response:

val in const int &ref = val; is a lvalue, not a prvalue. Even if it is converted to a prvalue, this doesn't mean creation of a temporary in either C 11 or C 17. In C 17 this isn't the case since only prvalue-to-xvalue conversion (and some special cases not relevant here) creates a temporary, while in C 11 [conv.lval]/2 says that only for class types lvalue-to-rvalue conversion creates a temporary.

The initialization of a reference is explained in [dcl.init.ref].

In C 11, all previous cases fall through and so according to [dcl.init.ref]/5.2.2 a temporary of the destination type is created and initialized by copy-initialization from the initializer expression and the reference is bound to that temporary. In this copy-initialization the lvalue val is converted to a prvalue of type double and then to a prvalue of type int, neither of these steps creating additional temporaries.

In C 17, all cases fall through until [dcl.init.ref]/5.2.2, which states that the initializer expression is first implicitly converted to a prvalue of the destination type, which does not imply creation of a temporary, and then the temporary materialization conversion (prvalue-to-xvalue conversion) is applied and the reference bound to the result, i.e. the xvalue referring to the temporary.

In the end there is always exactly one temporary, the one created according to the rule in [dcl.init.ref].

CodePudding user response:

Here's my take for C 17:

double val = 4.55;
const int &ref = val;

We're binding a const int reference to the lvalue expression of type double denoted by val. According to the declaration of references;

Otherwise, the initializer expression is implicitly converted to a prvalue of type “T1”.

we convert the expression val to type int. Note that this implicit type! conversion fits with the draft. Next,

The temporary materialization conversion is applied, considering the type of the prvalue to be “cv1 T1”, ...

in order to apply the temporary materialization (also known as prvalue -> xvalue conversion), we must have fully matched types so the expression is additionally converted to const int (source). The value category remains the same (prvalue). And finally,

... and the reference is bound to the result.

we have a reference binding of type T to a prvalue of type T which induces temporary materialization (source) and val gets converted to xvalue. The created temporary object is of type const int and value of 4.

  • Related