左值 (lvalue, locator value) 表示了一个占据内存中某个可识别的位置(也就是一个地址)的对象。

右值 (rvalue) 则使用排除法来定义。一个表达式不是 左值 就是 右值 。 那么,右值是一个 表示内存中某个可识别位置的对象的表达式。

举例

上面的术语定义显得有些模糊,这时候我们就需要马上看一些例子。我们假设定义并赋值了一个整形变量:

  1. int var;
  2. var = 4;

赋值操作需要左操作数是一个左值。var 是一个有内存位置的对象,因此它是左值。然而,下面的写法则是错的:

  1. 4 = var; // 错误!
  2. (var + 1) = 4; // 错误!

常量 4 和表达式 var + 1 都不是左值(也就是说,它们是右值),因为它们都是表达式的临时结果,而没有可识别的内存位置(也就是说,只存在于计算过程中的每个临时寄存器中)。因此,赋值给它们是没有任何语义上的意义的——我们赋值到了一个不存在的位置。

然而,给函数返回的结果赋值,不一定总是错误的操作。例如,C++ 的引用让我们可以这样写:

  1. int globalvar = 20;
  2. int& foo()
  3. {
  4. return globalvar;
  5. }
  6. int main()
  7. {
  8. foo() = 10;
  9. return 0;
  10. }

这里 foo 返回一个引用,引用一个左值,因此可以赋值给它。实际上,C++ 中函数可以返回左值的功能对实现一些重载的操作符非常重要。一个常见的例子就是重载方括号操作符 [],来实现一些查找访问的操作,如 std::map 中的方括号:

  1. std::map<int, float> mymap;
  2. mymap[10] = 5.6;

之所以能赋值给 mymap[10],是因为 std::map::operator[] 的重载返回的是一个可赋值的引用。