当按值返回时,值参数是否隐式移动?

时间:2011-05-15 14:30:01

标签: c++ rvalue-reference move-semantics c++11

考虑以下功能:

Foo foo(Foo x)
{
    return x;
}

return x会调用复制构造函数还是移动构造函数? (让我们把NRVO留在这里。)

为了调查,我写了一个简单的Foo类,它只能移动但不可复制:

struct Foo
{
    Foo() = default;
    Foo(const Foo&) = delete;
    Foo(Foo&&) = default;
};

如果按值返回值参数时调用了移动构造函数,则一切都应该没问题。但是当前的g ++编译器抱怨return x,并出现以下错误消息:

error: deleted function 'Foo::Foo(const Foo&)'

如果我将return x替换为return std::move(x),一切都很好。由此我得出结论,如果需要,必须明确地从值参数移动。 g ++的行为是否符合要求?

2 个答案:

答案 0 :(得分:24)

如果有Foo的移动ctor,则应该选择它。

函数参数在返回语句中从复制省略中明确排除(FDIS§12.9p31,第一个子弹):

  
      
  • 在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象的名称(函数或catch子句参数除外)
  •   

然而,下一段明确地将移动因素重新考虑在内:

  

当满足复制操作的省略标准或满足时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,选择复制构造函数的重载决策首先执行,就好像该对象是由右值指定。 ...

(两个引号都强调我的意思。)

答案 1 :(得分:12)

这是有效的代码--G ++的行为是不符合的。 MSVC10确实支持这种行为。