Did you use to have some sort of intuition for what “lvalue” and “rvalue” meant? Are you confused about glvalues, xvalues and prvalues, and worry that lvalues and rvalues might also have changed? This post aims to give you a basic intuition for all five of them.
First, a warning: This post does not aim to give a complete definition of the five value categories. Instead, I only hope to give a basic intuition, which I hope will help to have in the back of your mind next time you need to look up the actual details of one of them. Feel free to flame me in the comment section, but I don’t promise I’ll bite! :)
Back before C++11, there were two value categories, lvalue and rvalue. The basic intuition was that lvalues were things with identities, such as variables, and rvalues were temporaries:
However, along came rvalue references and move semantics. On the surface, the old lvalue / rvalue distinction seems sufficient: Never move from lvalues (people might still be using them), feel free to move from rvalues (they’re just temporary anyway):
Why did I put “Can’t move” and “lvalue” in red in that diagram? It turns out that you might want to move from certain lvalues! For instance, if you have an lvalue you won’t be using anymore, you can
std::move() it to cast it to an rvalue reference. A function can also return an rvalue reference to an object with identity.
So as it turns out, whether something has identity, and whether something can be moved from, are orthogonal properties! We’ll solve the problem of moving from lvalues soon, but first, let’s just change our diagram to reflect our new orthogonal view of the world:
Clearly, there’s a name missing in the lower left corner here. (We can ignore the top right corner, temporaries which can’t be moved from is not a useful concept.)
C++11 introduces a new value category “xvalue”, for lvalues which can be moved from. It might help to think of “xvalue” as “eXpiring lvalue”, since they’re probably about to end their lifetime and be moved from (for instance a function returning an rvalue reference).
In addition, what was formerly called “rvalue” was renamed to “prvalue”, meaning “pure rvalue”. These are the three basic value categories:
But we’re not quite there yet, what’s a “glvalue”, and what does “rvalue” mean these days? It turns out that we’ve already explained these concepts! We just haven’t given them proper names yet.
A glvalue, or “generalized lvalue”, covers exactly the “has identity” property, ignoring movability. An rvalue covers exactly the “can move” property, ignoring identity. And that’s it! You now know all the five value categories.