modern c++, understanding of xvalue
现代C++只添加了一种新的"xValm"?函数返回的右引用是xvalue,这是定义的,就像函数参数中的右引用一样,它只能绑定到右值?这些理解正确吗?与本主题相关的问题和答案从学习者的角度来处理这个问题。在这里,我试图从设计师的角度来了解这个主题。例如,int b=3;int&;x=std::move(b);std::move的返回值是一个x value,它可以绑定到引用,这是由设计器设置的规则。(合理和可用)。设计器还可以设置XValue需要绑定左侧引用的规则,即使这不是一个好规则。
- 你有具体的例子吗?
- 我的问题是,它们是由C++设计器从零中定义或创建的吗?当然,设计者必须保证规则之间不冲突。例如,函数参数列表中的右引用是绑定到调用方参数后的左值,这是未定义的。我在网上查过答案,只是为了证明我的理解。
- void fcn(int&;a);int&;fcn2()返回42;fcn(32);//现在a是lvalue
- 简单地说,xvalue是一个lvalue(它指的是一个对象),它可以被使用,因为它会消失,或者因为没有人再关心它了。
- 错了!完全错了!!!!!xvalue同时属于glvalue和rvvalue!
- @好奇的家伙,我认为你的意思是说一个xvalue就像一个lvalue,因为两者都能识别对象。XValue和LValue是互斥的表达式子类别。
- @ AxFuldAxValm是一个传统的C/C++ LValk。我讨厌左值被重新定义。
- "是的,这个术语是一个火车残骸(就像C++的核心创新一样)。glvalue只是一个很好的旧左值:它们有一个标识,并不总是在本地生成,也没有众所周知的动态类型。新的右值也不是好的旧右值。完全陈旧的C++描述的断裂。
- @好奇心的glvalue和prvalue只会让学习者更加困惑。真正的新功能是"&;&;",当它出现在函数参数列表中时,它可以绑定到rValue;当它出现函数返回结果时,它是一个rValue/xValue可以绑定到前者。这些规则是由C++设计者设置的。我们只能跟着走。
注意这里的术语。函数参数或函数返回类型可以是右值引用类型,但不是XValue,因为术语"XValue"只适用于表达式。
每个表达式要么是左值,要么是XValue,要么是prValue。最常见的XValue类型是一个表达式,它调用一个函数,该函数的返回类型为右值引用类型。对右值引用类型执行强制转换的表达式也是XValue。表达式也可以通过其他几种方式成为xValue。
右值引用是一种类型。用右值引用类型声明的变量可以用xvalue或prvalue初始化,但不能用左值初始化(除非通过用户定义的转换)。记住,声明为右值引用的变量的名称是左值,而不是XValue!
1 2 3 4
| int n = 3; // 1
int&& r1 = static_cast<int&&>(n); // 2
int&& r2 = std::move(r1); // 3
int&& func(int&& arg); // 4 |
此代码示例中的表达式为:
- 3第1行:一个prvalue
- n第2行:左值
- static_cast(n)第2行:xvalue
- r1第3行:左值
- std::move(r1)第3行:xvalue
第4行中根本没有表达式。
- 我的问题在第2行和第3行。这些是现代C++中新定义的,称为"xValuy",对吗?设计者还可以避免创建"xvalue",将第2行和第3行命名为"lvalue"。
- "xvalue"有身份,设计师说它是可消费的,然后就可以消费了。
- 权限引用可以绑定到prvalue,一个"被动权限值",不受调用方控制,xaluve,一个由调用方创建的"主动权限值"。
- struct as int i;as&;&;f()return as();int main()f().i;//表达式f().i属于xValue类别,因为as::i是非引用类型的非静态数据成员,子表达式f()属于xVlaue类别。返回0;}
- 使用右参考是正确的吗?f()返回xvalue,但调用f()后,该值将消失。
- @john"xvalue"仅适用于表达式,"rvvalue引用"仅适用于类型和声明。这似乎是吹毛求疵,但了解它可以帮助避免一些混乱。在我的例子中,int&& r1 =中的r1是一个右值引用,但不是一个xvalue,因为它根本不是一个表达式。
- @John an左值是标识某个对象的普通表达式。术语prvalue代表"纯权利价值"。在C++ 17之前,PROVE标识临时对象,该对象通常在包含PROVE表达式的完整表达式的末尾被销毁。在C++ 17中,PROVE根本不是一个对象,只是一种初始化对象的方式的表示,只有在需要时才将这些实体化为临时对象。XValue(过期值)标识类似左值的对象,但可以像prValue一样初始化右值引用。
- @john-an-xvalue通常用于指定,尽管对象可能不会标识临时对象,但对于使用xvalue表达式"窃取"对象的任何对象来说都是可以的。当一个函数有一个带有右值引用类型的参数时,它通常可以假定可以从被引用对象中窃取,因为它要么是从prvalue初始化的(具体化一个临时对象),要么是从xvalue初始化的,这意味着有人明确地说可以从中窃取。
- @john-the-std::move函数除了提供一种从任何其他表达式构建xvalue表达式的好方法外,什么也不做。由于std::move总是返回右值引用类型,因此像std::move(var)这样调用std::move的表达式是xvalue。因此,您可以使用它来让C++知道您不再需要对象的旧值,并且传递的结果的任何函数都可以更改该对象。
- @在您的示例中,f().i是一个xvalue,这是正确的。函数f有一个问题:它返回了一个对只在函数体中有生存期的临时函数的引用,因此尝试使用结果总是无效的,即使是立即使用。
- 您的示例行4。调用函数后,它的返回结果是一个xvalue。这句话对吗?
- @john表达式func(2)将是一个xvalue。这是解析代码的一个特性,与函数是否被调用、是否被调用或是否被调用无关。表达式的结果是一个对象。
- int&;func(int&;arg);/4我指的是这个。不是func(2),这意味着调用了int&;func(int&;&;)。第4行中根本没有表达式。"
- @约翰,我不知道你的问题是什么。