Terminology 经常使用但很少定义的术语:左值
什么是左值?出现在赋值左边的东西,即可以赋值的东西 <>注意,在C++中,函数调用可能是一个LValuy:Terminology 经常使用但很少定义的术语:左值,terminology,language-theory,Terminology,Language Theory,什么是左值?出现在赋值左边的东西,即可以赋值的东西 注意,在C++中,函数调用可能是一个LValuy: int & func() { static int a = 0; return a; } 然后: 左值是可以分配给以下对象的值: lvalue = rvalue; 它是“left value”或“lefthand value”的缩写,基本上只是=符号左侧的值,即您分配给某个对象的值 作为非左值(即仅右值)的示例: 该代码不起作用,因为printf()(返回int的函数)
int & func() {
static int a = 0;
return a;
}
然后:
左值是可以分配给以下对象的值:
lvalue = rvalue;
它是“left value”或“lefthand value”的缩写,基本上只是=
符号左侧的值,即您分配给某个对象的值
作为非左值(即仅右值)的示例:
该代码不起作用,因为
printf()
(返回int
的函数)不能是左值,只能是右值。由于OP在问他的问题时有点懒(尽管有些人不同意,请参见评论),我也会懒,只是简单地将整个相关部分粘贴在这里,可能违反了一些版权法
对象是一个存储区域,它
可以检查并存储到。一
左值是指
这样一个物体。左值不等于零
必须允许修改
它指定的对象。例如,一个
const对象是一个左值,不能
可以修改。可修改一词
左值用于强调
左值允许指定的对象
既要检查也要改变。这个
以下对象类型是左值,
但不可修改的左值:
- 数组类型
- 不完整的类型
- 常量限定类型
- 对象是结构或联合类型,其成员之一具有 常量限定类型
我所知道的最好的解释之一可以在中找到 确定表达式是否为左值的另一种方法是询问“我可以获取它的地址吗?”。如果可以的话,这是一个左值。如果你不能,那就是右值。例如,&obj、&*ptr、&ptr[index]和&++x都是有效的(即使其中一些表达式很愚蠢),而&1729、&(x+y)、&std::string(“meow”)和&x++都是无效的。为什么这样做有效?运算符的地址要求其“操作数应为左值”(C++03 5.3.1/2)。为什么需要这样做?获取持久对象的地址是可以的,但是获取临时对象的地址是非常危险的,因为临时对象很快就会消失
它通常位于“=”运算符的左侧。然而,随着时间的推移,“左值”/“右值”的含义发生了变化。C++中添加了一个“不可修改的LValk”,它是任何不能赋值的值:数组和变量“const”是两个例子。在C语言中,不能分配给任何右值(见下文)。同样,在C++中,不能分配给不是用户定义的类类型的rValue/ 您可以说“左值”是一个表达式,它命名一个对象,该对象随时间持续存在并占用某些存储位置。是否可以指定给该表达式对于该分类并不重要。尤其是引用也是左值,因为它的名称会随着时间的推移而持续存在。以下所有内容都是左值,因为它们都引用命名对象。还要注意,
const
对左值没有任何影响
int a; lvalue: a;
lvalue: ++a;
int a[2]; lvalue: a;
int &ra = a; lvalue: ra;
int *pa = &a; lvalue: *pa;
术语“rvalue”用于文字量和枚举数值,以及不享受长寿乐趣的临时值,它们在完整表达式结束时会立即被销毁。对于右值,重要的不是持久性方面,而是值方面。C++中的函数是LValk,因为它们是持久的,并且它们有地址,即使它们不是对象。我在上面的左值概述中省略了它们,因为当只考虑对象时,更容易理解左值。以下所有值均为右值:
enum { FOO, BAR }; rvalue: BAR;
int a[2]; rvalue: (a+1);
rvalue: 42;
int a; rvalue: a++; // refering to a temporary
struct mystruct { }; mystruct f() { return mystruct(); } rvalue: f();
顺便说一句,通常您有一个左值,但运算符需要一个右值。例如,二进制内置“+”运算符添加两个值。左值表达式first and for all指定必须首先读取值的位置。因此,当您添加两个变量时,将发生“从左值到右值”的转换。标准规定左值表达式中包含的值是其右值结果:
int a = 0, b = 1;
int c = a + b; // read values out of the lvalues of a and b.
其他运算符不接受右值,但接受左值。它们不读取值。一个例子是操作员的地址,&
。不能获取右值表达式的地址。有些右值甚至不是对象:它们不占用任何存储空间。例如,文本(10,3.3,…)和枚举数值
那吓人的东西怎么有用?
区分左值和右值有几个好处
- 允许编译器省略对右值的存储和使用reg
int a; lvalue: a; lvalue: ++a; int a[2]; lvalue: a; int &ra = a; lvalue: ra; int *pa = &a; lvalue: *pa;
enum { FOO, BAR }; rvalue: BAR; int a[2]; rvalue: (a+1); rvalue: 42; int a; rvalue: a++; // refering to a temporary struct mystruct { }; mystruct f() { return mystruct(); } rvalue: f();
int a = 0, b = 1; int c = a + b; // read values out of the lvalues of a and b.
3 = 42;
int a, b[1], *c;
((flag ? foo() : bar())->pointed_to_by_struct_member[42])[0]