A prvalue is an expression whose evaluation initializes an object
or computes the value of an operand of an operator,
as specified by the context in which it appears,
or an expression that has type cvvoid.
The discussion of each built-in operator in
[expr.compound] indicates the category of the value it yields and the value categories
of the operands it expects.
For example, the built-in assignment operators expect that
the left operand is an lvalue and that the right operand is a prvalue and yield an
lvalue as the result.
User-defined operators are functions, and the categories of
values they expect and yield are determined by their parameter and return types.
Historically, lvalues and rvalues were so-called
because they could appear on the left- and right-hand side of an assignment
(although this is no longer generally true);
glvalues are “generalized” lvalues,
prvalues are “pure” rvalues,
and xvalues are “eXpiring” lvalues.
Despite their names, these terms apply to expressions, not values.
a class member access expression designating a non-static data member
of non-reference type
in which the object expression is an xvalue ([expr.ref]), or
a .* pointer-to-member expression in which the first operand is
an xvalue and the second operand is a pointer to data member ([expr.mptr.oper]).
In general, the effect of this rule is that named rvalue references are
treated as lvalues and unnamed rvalue references to objects are treated as
xvalues; rvalue references to functions are treated as lvalues whether named or not.
— end note]
[Example 1: struct A {int m;
};
A&&operator+(A, A);
A&& f();
A a;
A&& ar =static_cast<A&&>(a);
The expressions f(), f().m, static_cast<A&&>(a), and a + a
are xvalues.
The result of a glvalue is the entity denoted by the expression.
The result of a prvalue
is the value that the expression stores into its context;
a prvalue that has type cvvoid has no result.
A prvalue whose result is the value V
is sometimes said to have or name the value V.
The result object of a prvalue is the object initialized by the prvalue;
a non-discarded prvalue
that is used to compute the value of an operand of a built-in operator
or a prvalue that has type cvvoid
has no result object.
Whenever a glvalue appears as an operand of an operator that
requires a prvalue for that operand, the
lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]),
or function-to-pointer ([conv.func]) standard conversions are
applied to convert the expression to a prvalue.
Because cv-qualifiers are removed from the type of an expression of
non-class type when the expression is converted to a prvalue, an lvalue
of type constint can, for example, be used where
a prvalue of type int is required.
There are no prvalue bit-fields; if a bit-field is converted to a
prvalue ([conv.lval]), a prvalue of the type of the bit-field is
created, which might then be promoted ([conv.prom]).
Whenever a prvalue appears as an operand of an operator that
expects a glvalue for that operand, the
temporary materialization conversion is
applied to convert the expression to an xvalue.
The discussion of reference initialization in [dcl.init.ref] and of
temporaries in [class.temporary] indicates the behavior of lvalues
and rvalues in other significant contexts.
Unless otherwise indicated ([dcl.type.decltype]),
a prvalue shall always have complete type or the void type;
if it has a class type or (possibly multidimensional) array of class type,
that class shall not be an abstract class ([class.abstract]).
If a program attempts to access
the stored value of an object through a glvalue
whose type is not similar to
one of the following types the behavior is
undefined:43
If a program invokes
a defaulted copy/move constructor or copy/move assignment operator
for a union of type U with a glvalue argument
that does not denote an object of type cvU within its lifetime,
the behavior is undefined.
If a prvalue initially has the type “cvT”, where
T is a cv-unqualified non-class, non-array type, the type of
the expression is adjusted to T prior to any further analysis.
The composite pointer type of
two operands p1 and
p2 having types T1 and T2, respectively, where at least one is a
pointer or pointer-to-member type or
std::nullptr_t, is:
if T1 or T2 is “pointer to cv1void” and the
other type is “pointer to cv2T”,
where T is an object type or void,
“pointer to cv12void”,
where cv12 is the union of cv1 and cv2;
if T1 or T2 is “pointer to noexcept function” and the
other type is “pointer to function”, where the function types are otherwise the same,
“pointer to function”;
if T1 is “pointer to cv1C1” and T2 is “pointer to
cv2C2”, where C1 is reference-related to C2 or C2 is
reference-related to C1 ([dcl.init.ref]),
the qualification-combined type ([conv.qual])
of T1 and T2 or the qualification-combined type of T2 and T1,
respectively;
if T1 or T2 is
“pointer to member of C1 of type function”,
the other type is
“pointer to member of C2 of type noexcept function”, and
C1 is reference-related to C2 or
C2 is reference-related to C1 ([dcl.init.ref]),
where the function types are otherwise the same,
“pointer to member of C2 of type function” or
“pointer to member of C1 of type function”, respectively;
if T1 is
“pointer to member of C1 of type cv1U” and
T2 is
“pointer to member of C2 of type cv2U”,
for some non-function type U,
where C1 is
reference-related to C2 or C2 is reference-related to
C1 ([dcl.init.ref]), the qualification-combined type of T2 and T1 or the qualification-combined type
of T1 and T2, respectively;
In an unevaluated operand, a non-static class member can be
named ([expr.prim.id]) and naming of objects or functions does not, by
itself, require that a definition be provided ([basic.def.odr]).
If the original expression is an lvalue of class type,
it must have a volatile copy constructor to initialize the temporary object
that is the result object of the temporary materialization conversion.
— end note]
The expression is evaluated and its result (if any) is discarded.