What standard clause does this lvalue-to-rvalue conversion provide?

Given:

int main() { int x = 0; int y = x; // <--- } 

Can someone please tell me which standard article (preferred in 2003) is required to convert the expression x from lvalue to rvalue to initialize the object y ?

(Or, if I am mistaken and such a transformation does not occur, then I would also like to know!)

+7
c ++ language-lawyer
Jun 16 '11 at 18:12
source share
5 answers

It’s easier for me (if not 100% accurate) to think of lvalue-s as real objects and rvalue-s as a value stored in an object. The expression x is an lvalue expression that refers to the object x defined in the first line, but when it is used as the right part of the assignment to a type that is not a user-defined type, the actual value is read, and this is where the conversion from lvalue to rvalue is performed: read the contents of the object.

As for the specific proposal in the standard that this conversion dictates ... well, the closest I can think of is 4.1 [conv.lvalue] / 2 (converting Lvalue to Rvalue):

The value contained in the object indicated by lvalue is the result of rvalue.

The requirement that the right side of the assignment is the value of r is either implicit or absent in 5.17 [expr.ass], but this is true, or else the following expression will be an error, since rhs is the value of r and there is no rvalue-to-lvalue conversion:

 int x = 5; 

EDIT: for initialization, 8.5 [dcl.init] / 14, the last bullet (which refers to the fundamental types) of states (highlighting mine):

  • Otherwise, the initial value of the initialized object is the (possibly converted) value initializer expressions. [...]

This value means that the lvalue expression in your example is read (i.e. converted to rvalue). In any case, the previous paragraph, which referred to the assignment, could be applied here: if initialization requires the value lvalue, rather than rvalue, expression int i = 0; will be poorly formed.

+8
Jun 16 '11 at 18:25
source share

I really believe that this is somewhat intuitive (as others have already said - value is necessary, so there is an obvious need to convert the object pointer to the value it contains). The best I could come up with is 4p3:

An expression e can be implicitly converted to type T if and only if the declaration "T t = e;" well formed, for some invented time variable t (8.5). The effect of an implicit conversion is the same as performing a declaration and initialization, and then using a temporary variable as a result of the conversion. The result is an lvalue if T is a reference type (8.3.2) and rvalue otherwise. The expression e is used as an lvalue if and only if initialization uses it as an lvalue.

Note the “if and only if” at the end - the initializer is used as an rvalue for this, because initialization uses it as an rvalue (the result of the conversion). So, at 3.10p7

Whenever an lvalue appears in the context where the value of r is expected, the value of l is converted to rvalue; see 4.1, 4.2 and 4.3.




EDIT: the paragraph for entering 4p3 can be found at 8.5p16, the last bullet:

Otherwise, the initial value of the initialized object is the (possibly converted) value of the initializer expression.

Also note the comments below.

+8
Jun 16 '11 at 18:37
source share

The initializer has the following grammar:

 initializer: = initializer-clause ( expression-list ) initializer-clause: assignment-expression { initializer-list ,opt } { } 

In your example, x is an assignment-expression that follows this grammar production chain:

 conditional-expression ==> logical-or-expression ==> logical-and-expression ==> inclusive-or-expression ==> exclusive-or-expression ==> and-expression ==> equality-expression ==> relational-expression ==> shift-expression ==> additive-expression ==> multiplicative-expression ==> pm-expression ==> cast-expression ==> unary-expression ==> postfix-expression ==> primary-expression ==> id-expression ==> unqualified-id ==> identifier 

And the identifier "is the value of lvalue if the object is a function or variable" (5.1 / 4 "Primary Expressions").

So, in your example, the expression to the right of = is an expression that is an lvalue . Of course, this may be an rvalue , but it is not necessary. And there is no required lvalue-to-rvalue conversion.

I am not sure that there is value in knowing this.

+2
Jun 16 '11 at 18:50
source share

This is what you are looking for:

§3.10 / 7

Whenever an lvalue appears in the context where the value of r is expected, the value of l is converted to rvalue; see 4.1, 4.2 and 4.3.

And I think when you write int y = x , it basically copies the value contained in the object x , which is the value of lvalue, but the value itself is rvalue, so the context expects rvalue.

Section 4.1 / 2 states:

The value contained in the object indicated by lvalue is the result of rvalue.

Perhaps these two quotes clarify your doubts. Correct me if my understanding is wrong. I would like to learn new things.




Comment by @Tomalak:

My problem is that int & y = x; is valid, so in this case, of course, x cannot be the value of r. I don't know how inappropriate that the difference in my example does this, although

Well int &y = x DOES NOT copy the value. It simply creates an alias for the object itself. But, as I said before int y = x , basically copies the value, which is the value of r. Therefore, the context expects a value of r, since copying is performed here.

+1
Jun 16 '11 at 18:22
source share

3.10 Lvalues ​​and rvalues

1 Each expression is either an lvalue or rvalue value.

2 The value l refers to an object or function. Some value of the expression — class classes or cvqualified class type — also refers to objects. 47)

3 [Note: some built-in operators and function calls give lvalues. [Example: if E is an expression type of a pointer, then * E is the value of an lvalue expression relating to the object or function that E. points to. Like another For example, the function int & F (); profitability is an lvalue, so calling f () is an lvalue expression. ]

  • [Note: some builin operators expect lvalue operands. [Example: built-in assignment operators expect left operands to be lvalues. ] Other built-in operators give r values, and some expect them. [Example: unary and binary + arguments and rvalue value Results. ] The discussion of each built-in operator in clause 5 indicates whether it expects lvalue operands and whether it has lvalue value. ]

5 The result of calling a function that does not return a link is an Rvalue. User-defined function operators and whether such operators calculate or give lvalues ​​by their parameter and return types.

6 An expression that contains a temporary object resulting in a type without a reference is an rvalue (this includes explicitly creating an object using functional notation (5.2.3)).

7 Whenever an lvalue appears in the context where an r value is expected, the lvalue is converted to an rvalue; see 4.1, 4.2 and 4.3.

8 The discussion of the initialization reference in 8.5.3 and the temporary data in 12.2 indicate the behavior of lvalues ​​and rvalues ​​in other significant contexts.

9 Class values ​​may have cvqualified types; nonclass rvalues ​​always have cvunqualified types. Values ​​should always have full types or void type; in addition to these types, lvalues ​​can also be incomplete types.

10 The value of l for an object is necessary for changing, except that the value of the class type can also be used to change its referent under certain circumstances. [Example: a member function called for an object (9.3) can modify an object. ]

11 Functions cannot be changed, but function pointers can be modifiable.

12 A pointer to an incomplete type may be modifiable. At some point in the program, when the specified type is a complete object, at which pointer points can also be changed.

13 The referent should not change the expression (through this expression), except that if it has a class type and has a mutable component, this component can (7.1.5.1).

14 If an expression can be used to change the object to which it refers, the expression is called modifiable. A program that attempts to modify an object through an unmodifiable value lvalue or an rvalue expression is unformatted.

15 If a program tries to access the stored value of an object via l value other than one of the following types of behavior undefined48): - a dynamic type of an object, - a cvqualified version of a dynamic type of an object, - a type that is a signed or unsigned type corresponding to a dynamic type of an object , - a type that is a signed or unsigned type to a cvqualified version of a dynamic object type, - an aggregate or a union type that includes one of the above types among its members (including, recursively, a member of a subgroup and whether it contains a union), - a type that (possibly cvqualified) the base class type is a dynamic object type, - a char or unsigned char.

+1
Jun 16 '11 at 18:27
source share



All Articles