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

发布于 2024-11-07 12:18:08 字数 605 浏览 0 评论 0原文

考虑以下函数:

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++ 的行为是否符合规范?

Consider the following function:

Foo foo(Foo x)
{
    return x;
}

Will return x invoke the copy constructor or the move constructor? (Let's leave NRVO aside here.)

To investigate, I wrote a simple Foo class that is only movable but not copyable:

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

If the move constructor were invoked when returning value parameters by value, all should be fine. But the current g++ compiler complains about return x with the following error message:

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

If I replace return x with return std::move(x), everything is fine. From this I conclude that moving from value parameters must be done explicitly if desired. Is g++'s behavior conforming or not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏了南城 2024-11-14 12:18:08

如果 Foo 有移动向量,则应选择它。

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

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

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

当满足复制操作省略的条件或将满足除了源对象是函数参数的事实,并且要复制的对象由左值指定时,首先执行重载解析来选择副本的构造函数,就像对象是由右值指定的一样。 ...

(两段引文中的重点都是我的。)

If there is a move ctor for Foo, it should be selected.

Function parameters are explicitly excluded from copy elision in return statements (FDIS §12.9p31, first bullet):

  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter)

However, the next paragraph explicitly brings move ctors back into consideration:

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. …

(Emphasis is mine in both quotes.)

拥有 2024-11-14 12:18:08

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

This is valid code- G++'s behaviour is non-conformant. MSVC10 does support this behaviour.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文