即使复制构造函数不可用,返回的仅移动类型也会编译 [英] Returning move-only type compiles even though copy-constructor is unavailable

查看:88
本文介绍了即使复制构造函数不可用,返回的仅移动类型也会编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的编译没有错误:

#include <memory>

std::unique_ptr<int> f() {
    std::unique_ptr<int> x(new int(42));
    return x;
}

int main() {
    std::unique_ptr<int> y = f();
}

我认为 f()的返回值 x 复制初始化,但是 std :: unique_ptr 仅可移动类型。由于复制构造函数不可用,这怎么会不正确?标准中的相关条款是什么?是否有地方说 f()是仅移动类型,而不是return语句变成移动构造而不是复制构造?

I thought that the return value of f() was copy-initialized by x, but std::unique_ptr is a move-only type. How is it that this isn't ill-formed because the copy constructor isn't available? What is the relevant clause in the standard? Is there somewhere that says if f() is a move-only type than a return statement becomes a move construction instead of a copy construction?

推荐答案


我认为 f()的返回值是copy-由 x 初始化,但 std :: unique_ptr 是仅移动类型

I thought that the return value of f() was copy-initialized by x, but std::unique_ptr is a move-only type

f()的返回值确实是根据表达式 x ,但复制初始化并不总是暗示copy- construction 。如果表达式是右值,则将通过重载解析(假定存在move构造函数)来选择move构造函数。

The return value of f() is indeed copy-initialized from the expression x, but copy-initialization does not always imply copy-construction. If the expression is an rvalue, then the move constructor will be picked by overload resolution (assuming a move constructor is present).

现在,尽管表达式< return x; 语句中的code> x 是左值(可能会导致您认为我刚才写的内容不适用),在返回具有自动存储持续时间的命名对象的情况下,编译器应首先尝试将 id-expression 视为重载解析的右值。

Now although it is true that the expression x in the return x; statement is an lvalue (which may lead you to think that what I just wrote does not apply), in situations where a named object with automatic storage duration is returned, the compiler shall first try to treat the id-expression as an rvalue for overload resolution.


标准中的相关条款是什么?是否有地方说如果 f()是仅移动类型,而不是 return 语句则变成移动构造复制结构?

What is the relevant clause in the standard? Is there somewhere that says if f() is a move-only type than a return statement becomes a move construction instead of a copy construction?

根据C ++标准的第12.8 / 32段([class.copy] / 32,N4296草案):

Per paragraph 12.8/32 of the C++ Standard ([class.copy]/32, draft N4296):


当满足复制/移动操作的省略标准,但不满足异常声明和要复制的对象时由左值指定,或者 return 语句中的表达式是一个(可能带有括号的) id-expression 时,该命名为一个对象在主体中声明了自动存储期限或最里面的封闭函数或lambda-expression的参数声明子句中,首先执行重载分辨率以选择副本的构造函数,就好像该对象是由右值。 [...]

When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. [...]

这篇关于即使复制构造函数不可用,返回的仅移动类型也会编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆