左值 (lvalue, locator value) 表示了一个占据内存中某个可识别的位置(也就是一个地址)的对象。
右值 (rvalue) 则使用排除法来定义。一个表达式不是 左值 就是 右值 。 那么,右值是一个 不 表示内存中某个可识别位置的对象的表达式。
举例
上面的术语定义显得有些模糊,这时候我们就需要马上看一些例子。我们假设定义并赋值了一个整形变量:
int var;
var = 4;
赋值操作需要左操作数是一个左值。var 是一个有内存位置的对象,因此它是左值。然而,下面的写法则是错的:
4 = var; // 错误!
(var + 1) = 4; // 错误!
常量 4 和表达式 var + 1 都不是左值(也就是说,它们是右值),因为它们都是表达式的临时结果,而没有可识别的内存位置(也就是说,只存在于计算过程中的每个临时寄存器中)。因此,赋值给它们是没有任何语义上的意义的——我们赋值到了一个不存在的位置。
然而,给函数返回的结果赋值,不一定总是错误的操作。例如,C++ 的引用让我们可以这样写:
int globalvar = 20;
int& foo()
{
return globalvar;
}
int main()
{
foo() = 10;
return 0;
}
这里 foo 返回一个引用,引用一个左值,因此可以赋值给它。实际上,C++ 中函数可以返回左值的功能对实现一些重载的操作符非常重要。一个常见的例子就是重载方括号操作符 [],来实现一些查找访问的操作,如 std::map 中的方括号:
std::map<int, float> mymap;
mymap[10] = 5.6;
之所以能赋值给 mymap[10],是因为 std::map::operator[] 的重载返回的是一个可赋值的引用。