4 Standard conversions [conv]

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

A glvalue ([basic.lval]) of a non-function, non-array type T can be converted to a prvalue.57 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.58

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 ex of the set of potential results of e, and ex names a variable x that is not odr-used by ex ([basic.def.odr]),

the value contained in the referenced object is not accessed. [ Example:

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 due to 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 (possibly cv-qualified) std::nullptr_t, the result is a null pointer constant ([conv.ptr]). [ Note: Since no value is fetched from memory, there is no side effect for a volatile access ([intro.execution]), and an inactive member of a union ([class.union]) may be accessed.  — 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], [basic.stc.dynamic.safety]), the behavior is implementation-defined.

  • Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.

Note: 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 ISO C, in which non-lvalues never have cv-qualified types.