C/C++ 中“左值”和“右值”的命名背后的原因是什么?
6 回答
该标准提到了这一点:
左值(历史上称为左值,因为左值可能出现在赋值表达式的左侧)[...]
一个右值(历史上称为右值,因为右值可能出现在赋值表达式的右侧)[...]
也就是说,左值是您可以分配的东西,而右值是您可以分配的东西。
然而,这已经逐渐离真相越来越远了。一个无法分配的左值的简单示例是const
变量。
const int x = 5;
x = 6; // Error
当涉及运算符重载时,甚至可以在赋值的左侧出现右值。
我发现将左值视为引用存储在内存中的对象而将右值视为一个值(可能已从内存中读取)更有用。这些概念很好地反映了这个想法。一些例子:
- 左值到右值可以被认为是从内存中的对象读取值。
- 大多数运算符需要左值到右值的转换,因为它们使用对象的值来计算结果。
- 运算符 (
&
) 的地址需要一个左值,因为您只能获取内存中某物的地址。它不需要获取对象的值来计算其地址。 - 执行
std::move
将左值表达式转换为右值表达式可以被认为是欺骗编译器认为存储在内存中的对象实际上只是一个临时值。
然而,这也不是在所有情况下都成立。这只是一个合理的类比。
回到过去,“左值”意味着可以放在作业左侧的东西,而“右值”意味着可以放在作业右侧的东西。
如果您考虑它们可以出现在赋值运算符的哪一侧,那将非常直观:
left-value = right-value;
简单地说,lvalue
意味着你可以分配给它,rvalue
意味着它只能出现在操作符的右侧。
在 C 中,lvalue
并rvalue
反映在赋值运算符中的用法。rvalue
只能出现在 的右侧=
,而lvalue
可以出现在两侧。在 C++ 中,它类似,但更复杂。
有不可赋值lvalues
的常量变量。
这是简化(稍微复杂的)概念的结果。
lvalue
s 是左值,即“可以在赋值左侧”的值。同样,这是一种简化,并非所有左值都可以按原样直接分配(例如,数组不能,只有非const
数组的元素,因此需要下标)。
rvalues
是正确的值,那些只能在赋值表达式的右侧。
左值中的“l”源自“左”值(如赋值运算符的左侧);但是,它现在代表位置值,指的是占据内存中某个可识别位置(即具有地址)的任何对象。右值现在是任何不是左值的东西。