22

考虑以下函数:

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 xreturn std::move(x),一切都很好。由此我得出结论,如果需要,必须明确地从值参数移动。g++ 的行为是否符合要求?

4

2 回答 2

24

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

函数参数被明确排除在返回语句中的复制省略之外(FDIS §12.9p31,第一个项目符号):

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

但是,下一段明确地重新考虑了 move ctors:

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

(重点是我在两个引号中。)

于 2011-05-15T14:31:30.370 回答
12

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

于 2011-05-15T14:33:28.953 回答