非 const 复制构造函数在 C++17 下编译良好

Non-const copy constructor compiles fine with C++17

我想知道为什么下面的代码不能用 C++14 编译,但可以用 C++17 编译。自 C++17 以来有什么可以改变的想法吗?问题当然是关于 class A 的非常量复制构造函数。我使用的是 VS 2019。这段代码是否有效?

class A {
public:
    A() { }
    A(A& a) { }
};

A fun() {
    A a;
    return a;
}

int main()
{
    A a = fun();
}

来自编译器的消息:

  1. class A 没有合适的拷贝构造函数
  2. 初始化无法从 A 转换为 A
  3. 无法复制构造 class A 由于复制构造函数不明确或没有可用的复制构造函数

fun()A类型的纯右值,所以A a = fun();表示a是函数调用的结果对象,没有中间临时。

此文本在 C++17 中 [basic.lval]/2:

The result object of a prvalue is the object initialized by the prvalue;

对于 A a = A(A(A(A(A(fun()))))); 等也是一样的 - 所有纯右值的结果对象都是 a

return 语句的行为在 [stmt.return]/2:

the return statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function call by copy-initialization (11.6) from the operand.

结果对象可以通过afun的局部变量)的复制初始化成功初始化,因为它是一个非常量左值,所以复制构造函数采用非常量左值引用确实绑定到它。


在 C++17 之前 fun() 的 return 值是一个临时对象,然后 main 的 a 是临时对象的 copy/move-constructed,省略是可选(但必须存在有效​​的构造函数)。