本文转自:https://www.cnblogs.com/relaxease/p/16027916.html
C++的左值和右值
摘要
C++语言中的左值和右值是困扰我的知识点,今天将学习到的知识点整理一下,以理清概念。本文首先介绍了左值、右值的一般分类和概念,包括广义左值,将亡值和纯右值,然后介绍了我对左值和右值的理解:将左值理解成水桶,将右值理解成水,最后介绍了左值引用和对常量的左值引用。
表达式值的分类
本文说的左值(lvalue)和右值(rvalue),其中的“值”就是表达式(expression)的值。C++17标准定义了表达式值的分类,其主要分为3类:
- 广义左值(glvalue):在程序员编程时,程序员可以取地址的东西(对象、函数)。举例:变量、函数等。
- 纯右值(prvalue):在程序员编程时,程序员不可以取地址的东西。举例:字面值常量。
- 将亡值(xvalue):本身可以被程序员取地址,但是马上就不能被取地址了的东西。
这三种类别和左右值的关系图:
三种类别和左右值的关系图
总结一下,可以这么理解左值和右值:左值,就是可以取地址的东西;右值就是不可以取地址的东西。
左右值的理解
我把左值理解成水桶,右值理解成水。这样我感觉比较好记忆和理解。比如:
int x; //x左值,理解成一个水桶
x = 10; // 10是右值,理解成水
int *p = &x; // 可以对水桶取地址,找到放水桶的地址
&10; // 编译错误,水没有位置,不能取地址
int y = x; // 把x水桶里的水复制一份到y水桶。
又如:
int f() {
int x = 10; // x是一个水桶
return x; //但是要被返回了,也就是这个水桶要被“销毁”。
}
int main() {
f() = 10; //编译错误,水桶已被销毁,不能盛水了
return 0;
}
左值引用
左值引用,就是在水桶上贴上了一个标签,这个标签代表了水桶(其实变量名字也可以理解成水桶上的标签)。
比如:
int a = 10;
int &b = a; //贴上标签
注意到常量的左值引用可以绑定到字面值常量上,也就是说以下代码是正确的:
const int & c = 10; //编译正确,但是“10”是右值,理解成水,c是左值引用,理解成标签。
但是如果把左值引用理解成在水桶上贴标签的话,以上代码就与这个理解产生冲突了。毕竟“标签”不能贴到“水”上。
其实,编译器会创建一个隐藏的变量来让引用c
绑定到10
上。比如:
const int & c = 10;
//会被翻译成这样:
int __internal_unique_name = 10;
const int& c = __internal_unique_name;
也就是说,编译器会创建一个左值(理解成“水桶”)来存储10(理解成“水”),然后再让引用绑定到该左值上(理解成在水桶上贴标签)。
总结
本文介绍了对左值和右值的理解。如果有什么错误,希望读者可以批评指正!
参考
- [1]微软C++文档
- [2]Internal Pointers的博客
原创文章,作者:1402239773,如若转载,请注明出处:https://blog.ytso.com/273272.html