对 C++ 构造函数删除感到困惑

All*_*lie 3 c++ constructor initialization copy-initialization

这是我的课

class A {
public:
    A(int);
    A(A const&) = delete;
    A& operator=(const A& a) = delete;
// etc.
};
Run Code Online (Sandbox Code Playgroud)

在另一个文件中,我可以像这样调用构造函数:

auto foo = A(123);
Run Code Online (Sandbox Code Playgroud)

这解决了复制构造函数而不是我期望的构造函数,为什么?

error C2280: 'mynamspace::A::A(const mynamespace::A &)': attempting to reference a deleted function
Run Code Online (Sandbox Code Playgroud)

son*_*yao 6

auto foo = A(123);进行复制的初始化,在概念上,A(123)构建了一个临时A通过A::A(int)首先,然后foo是复制初始化由复制构造从临时(PSA不具有移动构造函数)。在 C++17 之前,代码格式错误,因为复制构造函数被标记为delete.

从 C++17 开始,由于强制复制省略,完全省略了复制构造,并且代码格式良好。

(C++17 起)首先,如果T是一个类类型并且初始化器是一个纯右值表达式,其 cv 非限定类型是与 相同的类T,初始化器表达式本身,而不是从它具体化的临时,用于初始化目标对象:参见复制省略

(强调我的)

(C++17 起)在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象被直接构建到存储中,否则它们将被复制/移动到那里。复制/移动构造函数不需要存在或可访问

请注意,在 C++17 之前,复制省略是一种优化,即使可以执行,复制/移动构造函数仍然必须存在且可访问。

这是一种优化:即使它发生并且/move (since C++11)没有调用复制构造函数,它仍然必须存在且可访问(就像根本没有发生优化一样),否则程序是格式错误的:

您可以升级您的编译器以支持 C++17,或使用直接初始化(删除使用复制构造函数的要求)。

A foo(123);
A foo{123};
Run Code Online (Sandbox Code Playgroud)