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

时间:2015-07-20 15:25:16

标签: c++ move rvalue-reference rvo xvalue

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

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

What expressions create xvalues?未涵盖此类到期值。

在以下情况下会改变吗?

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

返回语句中foo是否为x值?特别是,它是移动的候选人吗?对于RVO?或者应该使用return std::move(foo)

我不知道在第一种情况的return语句中将表达式foo分类为xvalue的正式规则是什么,所以我不能在第二种情况下测试它。

1 个答案:

答案 0 :(得分:2)

在该函数中,foo左值,类型为“Foo的右值引用”。当你返回它时,由于必须构造一个副本(由于返回值的类型),你构建一个全新的值,使bar(...)成为 prvalue ,按照§3.10.1.5:

  

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

由于在函数内foo左值,因此表达式return foo不是移动构造的候选者the copy constructor is selected

是的,RVO适用于此处,假设未先选择移动。这方面没有什么特别之处。根据§12.8.31:

  

在下列情况下(可以合并以消除多份副本),允许复制/移动操作(称为复制省略)的省略:

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

[...]

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

return foo;

最终结果(来自bar(...)表达式)在prvalue中,因为给定返回类型的事实,表达式相当于:

return Foo(foo);

表示从foo函数返回从bar复制的临时值。

  

重读回复,对我来说仍然没有意义。你说因为在函数内部,foo是一个左值,表达式return foo不是移动构造的候选者,并且选择了复制构造函数。为什么在一个案例中这是真的而不是另一个案例?

返回foo时,您必须从左值引用Foo创建新的foo值(因为您要返回副本)。这是由复制构造函数隐式完成的。因此return foo;相当于return Foo(foo)。鉴于foo是左值,选择了复制构造函数(而不是移动构造函数)。

现在,当你有了这个新的临时值(由foo构造)时,表达式bar(...)中出现的值本身就是一个prvalue。所以当你这样做时:

auto res = bar(...);

你必须从prvalue构造一个Foo副本。由于prvalue也是一个rvalue,因此选择了带有rvalue引用参数(move constructor)的构造函数。