即使copy-constructor不可用,也返回仅移动类型编译

And*_*zos 9 c++ c++14

以下编译没有错误:

#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();
}
Run Code Online (Sandbox Code Playgroud)

我认为返回值是f()由复制初始化的x,但是std::unique_ptr是一个只移动的类型.怎么这不是格式错误,因为复制构造函数不可用?标准中的相关条款是什么?是否存在某个地方,表示if f()是仅移动类型而不是return语句变为移动构造而不是复制构造?

And*_*owl 16

我认为返回值是f()由复制初始化的x,但是std::unique_ptr是一个只移动的类型

返回值f()确实是从表达式中复制初始化的x,但复制初始化并不总是意味着复制构造.如果表达式是rvalue,则移位构造函数将被重载决策选中(假设存在移动构造函数).

现在,虽然这是事实,表达xreturn x;语句,其中还附有自动存储持续时间命名对象的左值(这可能会导致您认为我只是写不适用),在的情况下,编译器将首先尝试将id-expression视为重载解析的右值.

标准中的相关条款是什么?是否存在某个地方,表明如果f()是仅移动类型而不是return语句变为移动构造而不是复制构造?

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

当满足复制/移动操作的省略标准时,但不满足异常声明,并且要复制的对象由左值指定,或者return语句中的表达式是(可能带括号的)id表达式时命名具有在最内层封闭函数或lambda-expression 的body或parameter-declaration-clause中声明的自动存储持续时间的对象,首先执行用于选择复制的构造函数的重载决策,就好像该对象由rvalue指定一样.[...]