首页 > 解决方案 > 对 C++ 构造函数删除感到困惑

问题描述

这是我的课

class A {
public:
    A(int);
    A(A const&) = delete;
    A& operator=(const A& a) = delete;
// etc.
};

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

auto foo = A(123);

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

error C2280: 'mynamspace::A::A(const mynamespace::A &)': attempting to reference a deleted function

标签: c++constructorinitializationcopy-initialization

解决方案


auto foo = A(123);执行复制初始化,在概念上,首先A(123)构造一个临时对象,然后A由复制构造函数从临时对象复制初始化(PS没有移动构造函数)。在 C++17 之前,代码格式错误,因为复制构造函数被标记为.A::A(int)fooAdelete

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

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

(强调我的)

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

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

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

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

A foo(123);
A foo{123};

推荐阅读