1. 左值
左值通俗理解就是“可寻址的对象”,即某些表达式所代表的变量或内存中已命名位置。 程序员可以取地址并对其进行修改。 常见例子有:
-
变量:
int x;中x就是一个左值,因为它相当于内存中的一个已命名位置,且程序可以通过引用或指针来访问或修改它的内容。 -
已定义数组元素:
int a[5]; a[1] = 0;中a[1]就是一个左值,因为它是一个具体的内存位置,程序可以通过数组下标或指针来访问或修改它的数据。 -
引用:
int &ref = x; ref = 42;中ref就是一个左值,因为它实际上是引用了x这个变量,在使用时相当于x的别名。程序可以通过ref直接修改x的值。需要注意的是,虽然左值通常被理解为“变量”,但实际上也包括以函数返回值或取地址运算符
&获取的左值引用等其他情况。
2. 右值
右值通俗理解就是一个具体的、或不可寻址的值。程序只能读取该值,无法对其进行修改。 常见例子有:
- 字面量:
int i = 123;中的123就是一个右值,因为它只代表具体的数值,程序无法对这个数值做出任何修改。 - 计算表达式:
int b = 2 + 3;中的2 + 3是一个右值,因为它是由两个字面量相加得到的计算结果,结果本身是一个临时值,在内存中没有具体位置。 - 函数返回值:
int func() { return 42; } int c = func();中的func()返回的结果是一个右值,因为它是函数内部运算的结果,处于栈上的临时值。 - 函数返回的引用:
int x = 0; int& getRef(int &y) { return y; } int& ref = getRef(x);中的getRef(x)返回的结果是一个左值引用,但整个表达式作为右值使用,因此是一个右值。 - 取地址运算符 &:
int x = 0; int *p = &x;中,&x是一个左值,因为它获取了x的地址(即某个内存位置),程序可以将其存储到指针中并随后修改或访问相应的数据。但当&x的值赋给指针变量p(如int *p = &x;)时,整个表达式成为一个单一的右值。
3. 左值和右值的区别
- 左值可以出现在赋值运算符“=”的左边或右边,而右值只能出现在“=”的右边。
- 左值代表了有名字的、可寻址的内存位置或变量,而右值代表了一个具体的数值或临时计算结果,并不一定对应真正的内存位置或变量。
- 左值可以通过指针或引用进行访问或修改,而右值不能直接修改。
4. 总结
《C++ Primer 5th》的定义:当一个对象被用作左值的时候,用的是对象的身份(在内存中的位置);当一个对象被用作右值的时候,用的是对象的值(内容)。
总之,左值和右值的区别主要在于其是否拥有可寻址的内存空间以及能否被修改。