Are all xvalues
glvalues
and rvalues
at the same time? Or a xvalue
may be either glvalue
or a rvalue
?
If it's a glvalue
or/xor rvalue
, can you give a example for each case?
Are all xvalues
glvalues
and rvalues
at the same time? Or a xvalue
may be either glvalue
or a rvalue
?
If it's a glvalue
or/xor rvalue
, can you give a example for each case?
I think the key to understanding value categories is to understand the difference between a value and an object. A value is just an abstract instance of a type, one of all the possible bit patterns that makes up the information associated with an instance of a particular type. An object, on the other hand, is a particular piece of storage set aside at a particular location in memory in such a way that a value of a particular type can be stored in that location. We say the object holds a value of that type.
Think of the whole prvalue, xvalue, lvalue business like this: A prvalue is just a value of a given type, it is not necessarily stored anywhere. It really just is a value of a given type, existing only for an instant, at the one point in the particular expression in which it occurs. An lvalue, on the other hand, identifies a particular object in which a value of a particular type is stored. The object has a certain, well-defined time during which it is alive and keeps whatever value is stored inside of it. An lvalue is not a value of a particular type itself, it identifies an object that holds a value of a particular type. Thus, prvalue and lvalue sort of sit at two opposite ends on a spectrum, a prvalue being just a value in no particular storage with no persistence while an lvalue identifies a particular piece of storage persistently holding some value. An xvalue is something in between. An xvalue identifies a particular object at a particular location, the value stored in which, however, is not needed anymore. In that sense, an xvalue shares properties with both, lvalues and prvalues: it identifies an object at a particular location, but the value stored in that object does not have persistence:
explicit storage location persistence
prvalue no no
xvalue yes no
lvalue yes yes
What prvalue and xvalue have in common is the lack of persistence, which is the defining characteristic of a general rvalue. What xvalue and lvalue have in common is the particular storage location, which is the defining characteristic of a general glvalue. An xvalue is just an lvalue that has no persistence and, thus, can be treated like an rvalue…
From cppreference:
An rvalue expression is either prvalue or xvalue.
an xvalue (an “eXpiring” value) is a glvalue that denotes an object or bit-field whose resources can be reused;
Answering your questions:
Are all xvalues glvalues and rvalues at the same time?
Yes. More specifically, rvalue is a superset of prvalue and xvalue. Thus all xvalues are rvalues, but not all rvalues are xvalues (namely, the ones that are prvalues). And by the definition above, xvalue is a reusable glvalue. So xvalues are both glvalues and rvalues.
Or a xvalue may be either glvalue or a rvalue?
No. xvalue is purely a reusable glvalue, and reusable glvalues (i.e. xvalues) are rvalues. Think move semantics.
Examples:
int a = 6;
foo(6); // 6 is a prvalue (and thus is an rvalue)
foo(a); // a is a glvalue
std::vector<int> vec = {1, 2, 3};
bar(vec); // vec is a glvalue
bar(std::move(vec)); // std::move(vec) is an xvalue (reusable glvalue)
// (and thus is an rvalue)