Nazwy l-wartość i r-wartość są dość nieszczęśliwe (nie są wartościami jak sugeruje nazwa, a wyrażeniami). Nazywa się je tak ze względów historycznych. L-wartości pojawiały się bowiem po lewej stronie operatora przypisania, a r-wartości po prawej (por. left- i right-hand side odpowiednio). Nie wchodząc w meandry taksonomii kategorii wyrażeń, l-wartość odpowiadają obiektom, do których można odwołać się przez nazwę, wskaźnik lub odwołanie do l-wartości. Dodatkowo, l-wartość bez cechy const może zostać użyta jako lewy operand operatora przypisania. Przydatna heurystyka: jeśli można wziąść adres wyrażenia, jest (zazwyczaj) l-wartością; jeśli nie jest to najprawdopodobniej r-wartość. Przykład:
int foo(int&& x) {
return 2 * x; // 2 to r-wartość, x to l-wartość (decltype(x) to int&&),
// wyrażenie 2 * x to r-wartość
}
int main() {
std::cout << foo(3); // std::cout to l-wartość, foo(3) to r-wartość,
// std::cout << foo(3) to l-wartość (bo typem zwracanym przez
// przeciążony operator<< jest referencja do l-wartości)
}