En este artículo de MSDN hay una explicación breve y bastante clara. Te traduzco (énfasis mío):
Todas las expresiones de C++ son o un lvalue o un rvalue. Un lvalue es un objeto que persiste más allá de una expresión. Se puede pensar en un lvalue como en un objeto que tiene un nombre. Todas las variables, incluyendo las no modificables (const) son lvalues.
Un rvalue es un valor temporal que no persiste más allá de la expresión en la que se usa.
Para entender mejor la diferencia entre lvalue y rvalue, considera el siguiente ejemplo:
// lvalues_y_rvalues1.cpp
// compilar con: /EHsc
#include <iostream>
using namespace std;
int main()
{
int x = 3 + 4;
cout << x << endl;
}
Aquí x
es un lvalue porque persiste más allá de la expresión que lo define. La expresión 3+4 es un rvalue porque se evalúa a un valor temporal que no persiste más allá de la expresión.
A continuación algunos ejemplos de usos incorrectos de lvalues y rvalues:
// lvalues_and_rvalues2.cpp
int main()
{
int i, j, *p;
// Uso correcto: la variable i es un lvalue.
i = 7;
// Uso incorrecto: el operando a la izquierda debe ser un lvalue (C2106).
7 = i; // C2106
j * 4 = 7; // C2106
// Uso correcto: el puntero desreferenciado es un lvalue.
*p = i;
const int ci = 7;
// Uso incorrecto: la variable es un valor no modificable (C3892).
ci = 9; // C3892
// Uso correcto: el operador condicional devuelve un lvalue.
((i < 3) ? i : j) = 7;
}
TL;DR (no es parte del original): A un lvalue le puedes asignar un valor (si no es const
). A un rvalue no, pero puedes usarlo como el valor que asignas a un lvalue.