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

fre*_*low 22 c++ rvalue-reference move-semantics c++11

考虑以下功能:

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

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

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

struct Foo
{
    Foo() = default;
    Foo(const Foo&) = delete;
    Foo(Foo&&) = default;
};
Run Code Online (Sandbox Code Playgroud)

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

error: deleted function 'Foo::Foo(const Foo&)'
Run Code Online (Sandbox Code Playgroud)

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

Fre*_*urk 24

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

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

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

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

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

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

  • Upvoted.这是对草案的一个相对较晚的变化,这解释了为什么它还没有在任何地方实施.http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1148 (9认同)

Pup*_*ppy 12

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

  • @Matthieu:我没有说它有效*因为*MSVC10支持它.这是有效的,因为标准是这样说的. (2认同)
  • 我明白了,但仍然没有理由:) (2认同)