示例:
来看一行简单的代码
1 |
int a = 10;
|
这行代码,"=" 左边就是左值,"="右边的则为右值,那他们到底有什么不同呢?
如果是Java、PHP等后端同学,会称以左边的"a"为变量,右边的"10"为字面量,而到了C++这里,我们就需要对他理解更多一点。
这行代码运行起来,是在系统内存中申请了一块空间,命名为"a",然后把"10"这个值装入了这个单内存空间中,内存中的空间是有地址的,并且和"a"这个名字绑在一起,当我们提到"a",就能知道他所代表的内存地址,这也是所谓的"可寻址"。
在C++中,每个表达式都具有一个值和一个类型。左值和右值描述了表达式的可寻址性和持久性。
首先,让我们来看一下左值的概念。左值是指可以被取地址的表达式,或者说具有标识符的表达式。左值表示一个内存位置,它具有持久性,可以在程序的不同部分访问和修改。简而言之,左值可以出现在赋值运算符的左边。
左值的特点
1 2 3 |
int x = 10; // 'x' 是一个左值,可以被赋值
int * p = &x; // '&x' 是一个左值,可以取其地址
int arr[5]; // 'arr' 是一个左值,可以被访问和修改
|
接下来,我们来看一下右值的概念。右值是指不可被取地址的表达式,或者说临时生成的表达式。右值表示一个临时的值,它通常只能用于赋值或传递给函数,没有持久性。简而言之,右值可以出现在赋值运算符的右边。
右值的特点
1 2 3 |
int a = 5; // '5' 是一个右值
int b = a + 3; // 'a + 3' 是一个右值
int * ptr = new int (10); // 'new int(10)' 返回一个右值
|
需要注意的是,C++11引入了右值引用的概念,即可以对右值进行引用的类型。右值引用允许我们更有效地管理资源,如移动语义和完美转发。
综上所述,左值表示持久的可寻址表达式,而右值表示临时的不可寻址表达式。理解左值和右值的概念对于理解C++中的赋值、函数调用和参数传递等操作是非常重要的。
函数返回值
那么,一个函数返回值,应该是左值还是右值?
当一个函数被调用时,它会在栈上创建一个新的帧来存储该函数的局部变量、参数以及其他信息。该帧在函数返回时销毁。
因为函数返回值通常是通过寄存器或者特殊寄存器(如eax)返回的,它们的地址在栈帧被销毁后就不能再访问了。所以不能直接对函数返回值取址。
但是,如果你需要返回一个指向已经存在的内存块的指针,然后在函数外使用该指针访问内存块,那么是可以的。例如:
1 2 3 4 5 6 7 8 9 10 |
int * foo() {
int x = 10;
return &x;
}
int main() {
int * p = foo();
std::cout << *p; // undefined behavior
return 0;
}
|
上述代码中的foo()函数返回了一个指向局部变量x的指针。
这会导致undefined behavior,因为x在函数返回时就被销毁了,所以p指向的内存块中可能包含任意的值。
所以,不能直接对函数返回值取址,函数返回值是一个右值。
标签:10,函数,右值,int,左值,C++,表达式 From: https://www.cnblogs.com/zhuchunlin/p/18337006