【问题标题】:Returning move-only type compiles even though copy-constructor is unavailable即使复制构造函数不可用,返回仅移动类型也会编译
【发布时间】:2015-04-09 05:45:00
【问题描述】:

下面的编译没有错误:

#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() 是仅移动类型,而不是返回语句变成移动构造而不是复制构造?

【问题讨论】:

标签: c++ c++14


【解决方案1】:

我以为f()的返回值被x复制初始化了,但是std::unique_ptr是只移动类型

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

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

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

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

当满足省略复制/移动操作的条件时,但不符合异常声明,并且要复制的对象由左值指定,或 return 语句中的表达式时是一个(可能带括号的)id-expression,它命名一个对象,该对象具有在主体中声明的自动存储持续时间或最内层封闭函数或 lambda 表达式的参数声明子句,首先执行为副本选择构造函数的重载决议,就好像对象由右值指定一样。 [...]

【讨论】:

  • .. 因此移动构造函数是合格的,呈现 “f() 的返回值被 x 复制初始化” false。 &lt;/completed-this-answer&gt;
  • 最好说出您引用的 哪个 C++ 标准,因为已经有好几个了。
  • @LightnessRacesinOrbit:它不会使该声明为假。 AFAIK 复制初始化并不意味着复制构造。关于标准版本,将对其进行编辑,谢谢。
  • @AndyProwl:哦,好吧,在那种情况下,OP 有一个误解(“f() 的返回值被 x 复制初始化,但 std::unique_ptr 是一个移动-唯一类型。由于复制构造函数不可用,这怎么不是格式错误的?”)所以答案仍然可以使用结论。
  • @LightnessRacesinOrbit:同意,将详细说明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-14
  • 2021-09-20
相关资源
最近更新 更多