【问题标题】:modern c++, understanding of xvalue [duplicate]现代c ++,对xvalue的理解[重复]
【发布时间】:2018-11-12 17:10:02
【问题描述】:

现代 C++ 只增加了一种新类型“xvalue”?函数返回的右引用是xvalue,this是定义的,就像函数参数中的右引用一样,只能绑定右值?这些理解正确吗? 与此主题相关的问题和答案从学习者的角度处理此问题。这里我尝试从设计师的角度去了解这个话题。例如,int b =3; int&& x = std::move(b); std::move 的这个返回值是一个 xvalue,它可以绑定到 rreference,这是设计者设定的规则。 (合理可用)。设计者也可以设置xvalue需要绑定左引用的规则,虽然这不是一个好规则。

【问题讨论】:

  • 你有具体的例子吗?
  • 我的问题是它们是由 C++ 设计师从无到有定义或创建的吗?当然,设计者必须保持规则不相互冲突。例如,函数参数列表中的右边ref是绑定到调用者参数后的左值,这被扣除未定义。我在网上查了答案,这里只是为了验证我的理解。
  • void fcn(int && a); int&& fcn2() { return 42;} fcn(32);//现在a是左值
  • 简单地说,xvalue 是一个左值(它指的是一个对象),因为它会消失或者因为没有人再关心它,所以可以使用它。
  • @curiousguy glvalue 和 prvalue 只会让学习者更加困惑。真正的新东西是“&&”,当它出现在函数参数列表中时,它可以绑定到右值;当出现函数返回结果时,它是一个可以绑定到前者的rvalue/xvalue。这些规则是由 c++ 设计者设定的。我们只能跟随。

标签: c++ xvalue


【解决方案1】:

请注意此处的术语。函数参数或函数返回类型可能具有/是右值引用类型,但不是 xvalue,因为术语“xvalue”仅适用于表达式。

每个表达式要么是左值,要么是 xvalue,要么是 prvalue。最常见的 xvalue 类型是调用具有右值引用类型作为其返回类型的函数的表达式。对右值引用类型进行强制转换的表达式也是一个 xvalue。表达式也可以通过其他几种方式成为 xvalue。

右值引用是一种类型。用右值引用类型声明的变量可以用 xvalue 或 prvalue 初始化,但不能用左值初始化(除非通过用户定义的转换)。请记住,声明为右值引用的变量的名称是左值,而不是 xvalue!

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&lt;int&amp;&amp;&gt;(n) 在第 2 行:一个 xvalue
  • r1 第 3 行:一个左值
  • std::move(r1) 在第 3 行:一个 xvalue

第 4 行根本没有表达式。

【讨论】:

  • @John "xvalue" 仅适用于表达式,而 "rvalue reference" 仅适用于类型和声明。这可能看起来像吹毛求疵,但理解它可以帮助避免一些混淆。所以在我的例子中,int&amp;&amp; r1 = 中的 r1 是一个右值引用,但不是一个 xvalue,因为它根本不是一个表达式。
  • @John 左值是标识某个对象的普通表达式。 prvalue 一词代表“纯正值”。在 C++17 之前,prvalue 标识了一个临时对象,该对象通常在包含 prvalue 表达式的完整表达式的末尾被销毁。从 C++17 开始,prvalue 根本就不是对象,只是一种初始化对象的方式的表示,并且这些仅在需要时才具体化为临时对象。 xvalue(过期值)像左值一样标识对象,但可以像纯右值一样初始化右值引用。
  • @John 一个 xvalue 通常用于指定尽管对象可能无法识别临时对象,但无论使用 xvalue 表达式“窃取”对象是什么都可以。当一个函数有一个带有右值引用类型的参数时,它通常可以假设从被引用的对象中窃取是可以的,因为它要么是从一个纯右值(物化一个临时对象)初始化的,要么是从一个 xvalue 初始化的,这意味着有人明确表示它是可以偷它。
  • @John std::move 函数只是提供了一种从任何其他表达式构建 xvalue 表达式的好方法。因为std::move 总是返回一个右值引用类型,所以像std::move(var) 这样调用std::move 的表达式是一个xvalue。因此,您使用它来让 C++ 知道您不再需要对象的旧值,并且将结果传递给的任何函数都可能更改该对象。
  • @John 在您的示例中,f().i 确实是一个 xvalue。而函数f 有一个问题:它返回一个临时引用,该临时引用只在函数体内有生命周期,所以尝试使用结果总是无效的,即使是立即使用。
猜你喜欢
  • 2018-07-08
  • 1970-01-01
  • 2014-02-16
  • 2016-09-06
  • 2023-03-16
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
相关资源
最近更新 更多