7 Expressions [expr]

7.3 Standard conversions [conv]

7.3.2 Lvalue-to-rvalue conversion [conv.lval]

A glvalue of a non-function, non-array type T can be converted to a prvalue.44
If T is an incomplete type, a program that necessitates this conversion is ill-formed.
If T is a non-class type, the type of the prvalue is the cv-unqualified version of T.
Otherwise, the type of the prvalue is T.45
When an lvalue-to-rvalue conversion is applied to an expression E, and either
  • E is not potentially evaluated, or
  • the evaluation of E results in the evaluation of a member of the set of potential results of E, and names a variable x that is not odr-used by ([basic.def.odr]),
the value contained in the referenced object is not accessed.
[Example 1: struct S { int n; }; auto f() { S x { 1 }; constexpr S y { 2 }; return [&](bool b) { return (b ? y : x).n; }; } auto g = f(); int m = g(false); // undefined behavior: access of x.n outside its lifetime int n = g(true); // OK, does not access y.n — end example]
The result of the conversion is determined according to the following rules:
  • If T is cv std​::​nullptr_t, the result is a null pointer constant ([conv.ptr]).
    [Note 1: 
    Since the conversion does not access the object to which the glvalue refers, there is no side effect even if T is volatile-qualified ([intro.execution]), and the glvalue can refer to an inactive member of a union ([class.union]).
    — end note]
  • Otherwise, if T has a class type, the conversion copy-initializes the result object from the glvalue.
  • Otherwise, if the object to which the glvalue refers contains an invalid pointer value ([basic.stc.dynamic.deallocation]), the behavior is implementation-defined.
  • Otherwise, the object indicated by the glvalue is read ([defns.access]), and the value contained in the object is the prvalue result.
    If the result is an erroneous value ([basic.indet]) and the bits in the value representation are not valid for the object's type, the behavior is undefined.
[Note 2: 
See also [basic.lval].
— end note]
For historical reasons, this conversion is called the “lvalue-to-rvalue” conversion, even though that name does not accurately reflect the taxonomy of expressions described in [basic.lval].
In C++ class and array prvalues can have cv-qualified types.
This differs from C, in which non-lvalues never have cv-qualified types.