即使复制构造函数不可用,也返回仅移动类型编译

时间:2015-02-09 13:07:15

标签: 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();
}

我认为f()的返回值是由x复制初始化的,但std::unique_ptr是一种仅移动类型。由于复制构造函数不可用,它是如何形成不良的呢?标准中的相关条款是什么?是否存在某个地方,如果f()是仅移动类型而不是返回语句变为移动构造而不是复制构造?

1 个答案:

答案 0 :(得分:16)

  

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

f()的返回值确实是从表达式x复制初始化的,但复制初始化并不总是暗示copy- 构造。如果表达式是rvalue,那么移动构造函数将被重载决策选中(假设存在移动构造函数)。

现在虽然x语句中的return x;表达式是左值(这可能会让您认为我刚写的内容不适用),但在命名对象的情况下确实如此如果返回自动存储持续时间,编译器应首先尝试将 id-expression 视为重载决策的右值。

  

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

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

  

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