按值返回的右值引用参数是 xvalue 吗?

2023-12-06

我的理解是,在下面的函数中,表达式foo在声明中return foo;是一个 xvalue,因为它表示的对象即将过期(即使foo是前面语句中的左值):

Foo bar()
{
    Foo foo;
    change(foo);
    return foo;
}

此类到期值不属于哪些表达式创建 x 值?.

在下面的情况下,情况会发生变化吗?

Foo bar(Foo&& foo)
{
    change(foo);
    return foo;
}

Is fooreturn 语句中的 xvalue?特别是,它是移动的候选者吗?那么 RVO 呢?或者应该使用return std::move(foo)?

我不知道对表达式进行分类的正式规则是什么foo作为第一种情况的返回语句中的xvalue,所以我无法在第二种情况中测试它。


在该函数中,foo is an lvalue类型为“右值引用Foo当你返回它时,由于必须构造一个副本(由于返回值的类型),所以你正在构造一个全新的值,这使得bar(...) an prvalue,根据 §3.10.1.5:

prvalue(“纯”右值)是不是 xvalue 的右值。 [ 示例:调用返回类型不是引用的函数的结果是纯右值。诸如 12、7.3e5 或 true 之类的文字值也是纯右值。 —结束示例]

由于以下事实:在函数内部,foo is an lvalue, 表达方式return foo不是移动构建的候选者并且选择复制构造函数.

是的,RVO 在这里适用,假设没有首先选择移动。在这方面这里没有什么特别的。根据第 12.8.31 条:

这种复制/移动操作的省略称为复制省略,在以下情况下是允许的(可以组合使用以消除多个副本):

  • 在具有类返回类型的函数的 return 语句中,当表达式是具有与函数返回类型相同的 cv- 非限定类型的非易失性自动对象(函数或 catch 子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作

[...]


澄清,foo本身是一个左值,但声明:

return foo;

最终结果(从bar(...)表达式)在纯右值中,因为给定返回类型,该表达式相当于:

return Foo(foo);

这意味着一个临时值,复制自foo从函数返回bar.


重读了一遍回复,我还是没有明白。你说由于事实上,在函数内部, foo 是一个左值,表达式 return foo 不是移动构造的候选者,并且选择了复制构造函数。为什么在一种情况下是这样,而在另一种情况下却不是这样?

返程时foo你必须创建一个新的Foo值(因为您要返回副本)lvalue参考foo。这是由复制构造函数隐式完成的。所以return foo;相当于return Foo(foo)。鉴于foo是左值,则选择复制构造函数(而不是移动构造函数)。

现在,当您有了这个新的临时值(由foo),值本身,来自表达式bar(...), 是纯右值。所以当你这样做时:

auto res = bar(...);

你必须构建一个Foo复制纯右值。由于纯右值也是右值,因此选择具有右值引用参数的构造函数(移动构造函数)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

按值返回的右值引用参数是 xvalue 吗? 的相关文章

随机推荐