0

该文档似乎是 C++11 中这些更改的来源:n3055

二、变更概览

右值,目前在核心语言子句中已知,被重命名为“<strong>prvalues”(“纯”右值)。

lvalues的含义没有改变,但是引入了glvalues来覆盖xvalues

为什么不对右值做同样的事情?!

rvalues 的含义应该保持不变,但也引入了grvalues来覆盖xvalues。(纯右值可以被替换回简单的右值,与值的定义方式对称)

      expression
      /        \
   glvalue    grvalue
   /     \    /     \
lvalue   xvalue   rvalue

可以更简单地定义值类别:

  • 左值具有标识不能从中移动;是不是 xvalue 的 glvalue
  • 右值没有身份,但可以; 是不是 xvalue 的 grvalue
  • 一个xvalue具有标识并且可以.

每个表达式都是左值xvaluervalue

4

1 回答 1

3

rvalues 的概念变得更加普遍,rvalues 的本质被确定为没有别名。添加了一个共享此属性的新值类别 xvalues,并且在 C++11 之前存在的右值子集被重命名为纯右值(“纯右值”)。

我们现在想要的两个主要部门是:

  • glvalue vs prvalue:glvalues是对象(=存储位置);prvalues 是传统的“临时”(但见下文)。
  • 左值与右值:左值绑定到左值引用,右值绑定到右值引用。这种区别是定义引用和引用绑定如何工作所需的区别。

xvalue 既是左值又是右值。这反映了右值引用是一种执行左值到极值转换(通过强制转换std::move)的方式,即具有用户定义的右值。通过将右值绑定到右值引用(现在是左值),它们还允许从右值到左值的另一个方向的转换。

C++17 通过将纯右值转换为不再是对象的“名义值”或“未实现的值”进一步完善了这个想法。在这张新图片中,只有 glvalues 是对象。然而,prvalue 可以具体化为对象,这被恰当地称为“prvalue-to-glvalue 转换”

这种考虑值类别的新方法意味着,如果你有一个函数T f();,其中T不是引用,那么表达式f()本身就不是对象(因此不需要复制对象!),而是在需要时(例如,如果你说f().x) ,创建一个对象并使用prvalue(=物化)进行初始化,以便允许成员访问。


也许总结一下 C++17 中存在的所有转换是有价值的:

  • “glvalue-to-prvalue”:这就是 C 所说的“左值转换”。示例:int a = 1; 1 + a;加法表达式的第二个操作数是prvalue,通过glvalue到prvalue的转换获得a

  • “右值到左值”:由右值引用提供。示例:int && r = e。这e是一个右值表达式,并且r是一个指定相同(或潜在物化)对象的左值。

  • “prvalue-to-glvalue”:这是prvalue的具体化,是预期的glvalue。

  • “lvalue-to-rvalue”:仅通过例如“lvalue-to-xvalue”实际可用std::move,例如int a; static_cast<int&&>(a);

请注意,列表中出现的所有对都具有相同数量的字母——要么都具有一个字母,要么都具有两个。我认为这是您提出的替代方案所缺乏的精心挑选的分类法的结果。

于 2017-12-02T13:53:52.540 回答