按照最原始通俗的理解就是以赋值操作符左右进行区分左值或者右值。但是一个左值也可以出现在赋值操作符的右边,那此时它就是右值了么?这里面其实是对左值进行了转换,转换成了相应的右值。因此单纯的以赋值操作符左右来区分就有些片面。
网上看到并且我也认可的定义:
左值是指具有对象类型或者非空不完整类型的表达式。L可以理解为location,表示可寻址的存储。
比方说int a = 10;a就是一个对象类型的表达式,它表示一个整型。同时,a表示一块内存存储,通过它可以寻址访问那一块内存,访问的规则是按照int来访问。
而右值是指表达式的值。
比方说一些临时变量、数值常量或者无名变量,在使用时我们只关心它的值,而无法通过这个表达式进行寻址访问内存,或者说实话它是否在内存中我们都不十分清楚。例如 100、a+1、a++等。
之前说单纯的按照等号左右来判别左值还是右值过于片面,第一是因为有时候没有赋值符号我们怎么判断呢?第二上文也提到过有时候进行的转换不易简单的看出来。因此我觉得就要稍微深入点理解为什么最初是以赋值符号左右进行区分,赋值,很明显是一个值赋予另一个,后者的值改变。那么本质上说,左值右值的区分是通过判断是否可以改变,一般认为左值是可以改变的,即通过这个特定的名字访问的存储内容可以改变;而右值是不可以改变的,因为没有一个特定的名字去访问那块存储。按照这种理解,可以改变的是左值,不可改变的是右值。但是还是有很多的例外:不可以改变的左值和可以改变的右值,前者是左值带有了右值性,后者是右值带有了左值性。但是const限定的左值跟这些没有关系,它只是受制于const而已。
先以函数的返回值来说,一般的函数返回值是右值。但有两个意外,
第一,如果函数返回值类型是引用,那么这个返回值就是一个左值,或者说是一个左值的引用,因为引用必然关联一个左值。所以当看到fun(a) = 900;之类的时候不要惊讶,另外,STL中重载[]的函数返回值就是引用,所以我们可以通过下边进行访问修改。
第二,就是返回值是指针类型的,fun(a)是一个右值,因为指针类型也是按值传递的,但*fun(a)就是一个左值,这跟*有关,因为*操作返回的是左值。
最后有一些规则的东西:有些左值右值的规则也要大致了解些:比如自增/自减运算符、取地址操作符&、成员运算符.要求操作数是左值;而解析操作符*的运算结果是左值;&运算结果是右值;数组名、函数、枚举常量、强制类型转换、函数调用等表达式不能产生lvalue。
以上是看了很多东西自己总结的,未必对,但这么理解暂时也是过得去的。
本文深入探讨了左值与右值的概念,包括它们的基本定义、区别以及在不同场景下的应用实例,如函数返回值、赋值运算符、自增/自减运算符等,并详细解释了这些概念在编程实践中的重要意义。
121

被折叠的 条评论
为什么被折叠?



