什么表达式创建xvalues?

Per*_*est 25 c++ language-lawyer xvalue c++11

我正在尝试理解C++ 11的概念.

我所说的标准草案:

xvalue("eXpiring"值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源).xvalue是涉及rvalue引用的某些表达式的结果(8.3.2).[示例:调用返回类型为右值引用的函数的结果是xvalue. - 末端的例子]

那么,产生xvalues的"某种表达式" 到底什么?规范的这一部分没有详细说明这些表达式的列表.

我理解左值和右值(至少我认为,我理解).

Jam*_*lis 19

在§5(C++11§5[expr]/6)的引言中有一个有用的非规范性说明:

[注意:表达式是xvalue,如果它是:

  • 调用函数的结果,无论是隐式还是显式,其返回类型是对象类型的右值引用,

  • 强制转换为对象类型的右值引用,

  • 一个类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式是xvalue,或者

  • 一个.*指针到构件表达,其中第一操作数是一个x值和第二个操作数是一个指向数据成员.

通常,此规则的作用是将命名的右值引用视为左值,将对象的未命名右值引用视为xvalues; 对函数的右值引用被视为左值,无论是否命名. - 尾注]

搜索§5的其余部分,此列表似乎详尽无遗.该列表后跟一个示例:

struct A {
    int m;
};

A&& operator+(A, A);
A&& f();
A a;
A&& ar = static_cast<A&&>(a);
Run Code Online (Sandbox Code Playgroud)

表达f(),f().m,static_cast<A&&>(a),和a + a是xvalues.表达式ar是左值.

获取xvalue表达式有两种常用方法:

  • 使用std::move移动对象. std::move执行一个static_castrvalue引用类型并返回rvalue引用.

  • 使用std::forward转发右值. std::forward通常用在函数模板中以实现函数参数的完美转发.

    如果提供给函数模板的参数是rvalue,则参数类型将是rvalue引用,它是一个左值.在这种情况下,std::forward执行一个static_castrvalue引用类型并返回rvalue引用.

    (注意:如果提供给函数模板的参数是左值,则参数类型将是左值引用,std::forward并将返回左值引用.)


asc*_*ler 6

第5节描述了有效表达式的语法,为每个表达式语法列出了表达式为左值,x值或prvalue的条件.第5条中可能的x值的完整列表是:

5.2.2第10段:如果结果类型是对象类型的右值引用,则函数调用是... xvalue.

(在标准的技术语言中,"对象类型"并不等同于"类类型"."对象类型"包括基本类型,指针和数组,并且仅排除函数类型.函数类型的右值引用始终被视为左值,而不是xvalue.)

返回右值引用的最值得注意的函数当然是std::move有时候std::forward.

5.2.5第4段:If E2是非静态数据成员...如果E1是xvalue,则E1.E2是xvalue

(另一方面,数据成员查找E1->E2始终是左值.)

类似地,如果E1是xvalue,则数据成员查找E1.*E2是xvalue:

5.5第6段:.*第二个操作数是指向数据成员的指针的表达式的结果与第一个操作数具有相同的值类别(3.10).

对于各种类型的演员:

  • dynamic_cast<Type>(expr):5.2.7第2段
  • static_cast<Type>(expr):5.2.9第1段
  • reinterpret_cast<Type>(expr):5.2.10第1段
  • const_cast<Type>(expr):5.2.11第1段
  • (Type) expr:5.4第1段

表达式是一个xvalue,当且仅当它Type是对象类型的右值引用时.Type(expr)从那以后也是如此

5.2.3第1段:如果表达式列表[在类型名称后面的括号中]是单个表达式,则类型转换表达式与相应的强制转换表达式(5.4)等效(在定义中,如果在意义上定义).

(另一方面,Type{expr}始终是一个prvalue.)

关于条件运算符的第5.16节最后说A ? B : C如果B和/或C是x值,有时可以是x值.但完整的规则很难总结.

如果表达式最终调用用户定义的重载运算符函数,则5.2.2部分适用于该表达式,而不是描述内置运算符行为的表达式.(参见a + a@James发布的示例中的表达式.)