为什么返回非引用类型的函数表达式被认为是prvalues而不是xvalues?

Seb*_*Nag 7 c++ language-lawyer

§ 3.10.1.5从标准定义prvalue表达式为:

- prvalue("纯"rvalue)是一个不是xvalue的rvalue.[示例:调用返回类型不是引用的函数的结果是prvalue.诸如12,7.3e5或true之类的文字的值也是prvalue. - 结束例子]

因此该函数foo()是一个prvalue表达式:

class Foo {}; 
Foo foo() { return Foo{}; }
Run Code Online (Sandbox Code Playgroud)

要初始化lvalue reference to a non-volatile const type/ rvalue reference初始化表达式必须是(§ 5.2.1.1):

[...] xvalue(但不是位字段),类prvalue,数组prvalue或函数lvalue和"cv1 T1"与"cv2 T2"引用兼容,或[...]

从而,

Foo &&rrFoo_ = foo(); 
Run Code Online (Sandbox Code Playgroud)

是有效的代码rrFoo_绑定到延长对象生命周期的临时对象(§12.2):

类型的临时数在各种上下文中创建:绑定对prvalue的引用(8.5.3),返回prvalue(6.6.3),创建prvalue的转换(4.1,5.2.9,5.2.11,5.4) ,抛出异常(15.1),并在一些初始化(8.5)中.

如上所述并且忽略了RVO,以下类型对象的初始化Foo将复制移动构造临时从默认构造对象.然后用于复制move的临时对象构造名为的最终对象obj_foo:

Foo obj_foo{ foo() }; 
Run Code Online (Sandbox Code Playgroud)

因此,在这两种情况下,我们要么偷窃,要么延长临时对象的生命周期,否则会被破坏.

§3.10.1.2 将xvalues定义为:

xvalue("eXpiring"值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源).[...]

我想不出任何没有创建临时对象的情况.所以我的问题是,为什么函数表达式foo()被认为是prvalue表达式,即使它们至少具有类似的属性xvalues

小智 4

给定int f1()int && f2(),其意图decltype(f1())int,并且decltype(f2())int &&。其工作方式是指定 为f1()纯右值且f2()为 xvalue。decltype然后查看给定表达式是否是纯右值、x值或左值。如果f1()f2()都是x值,则仍然需要以其他方式进行相同的区分。