如果类包含用户声明的析构函数,那么复制构造函数是什么?

6 c++ constructor language-lawyer rule-of-three

12.8/7节中的标准说:

如果类定义没有显式声明复制构造函数,则会隐式声明一个.如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除; 否则,它被定义为默认值(8.4).如果 类具有用户声明的复制赋值运算符或用户声明的 析构函数,则不推荐使用后一种情况.因此,对于类的定义

struct X {
    X(const X&, int);
};
Run Code Online (Sandbox Code Playgroud)

隐式声明了复制构造函数.如果用户声明的构造函数稍后定义为

X::X(const X& x, int i =0) { /? ... ?/ }
Run Code Online (Sandbox Code Playgroud)

我无法理解如果该类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况.在示例中,标准既不提供用户声明的复制赋值运算符也不提供析构函数.如果我们声明析构函数或复制赋值运算符会发生什么?我试过这样做如下:

struct A
{
    ~A(){ };
};

A::A(const A&){ }; //error

int main(){ }
Run Code Online (Sandbox Code Playgroud)

DEMO

但在示例中,我们仍然具有隐式声明的复制构造函数.这个规则实际意味着什么?

我想如果我们写下面的内容:

struct A
{
    A(){ };
    A(const A&&){ };
    ~A(){ };
};

A a;

A t = a; //error: call to implicitly-deleted copy constructor of 'A'

int main()
{ 

}
Run Code Online (Sandbox Code Playgroud)

DEMO

复制构造函数不会被显式删除.但事实并非如此.

Col*_*mbo 5

这种弃用基本上包含了三(五)规则。如果提供了用户声明的复制赋值运算符或析构函数,则不推荐将复制构造函数定义为默认值(而不是已删除)这一事实。这应该可以防止您将来依赖这种隐式声明的复制构造函数。

在示例中,标准既没有提供复制赋值也没有提供析构函数是用户自定义的。

该示例与弃用无关。

我尝试这样做: [...] 但在示例中,我们仍然有隐式声明的复制构造函数。

你不能定义一个隐式声明的复制构造函数 - 因为它已经定义了= default(没有双关语)。您必须先自己声明。

我认为如果我们编写以下内容:[...] 复制构造函数不会被明确删除。但事实并非如此。

引用了明确指定如果声明移动构造函数,则复制构造函数将被隐式定义为已删除的规则:

如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;

清楚地,

A(const A&&){ }
Run Code Online (Sandbox Code Playgroud)

是根据 [class.copy]/3 的移动构造函数。如果您删除了此移动构造函数,则您的示例将编译,尽管它使用了所述已弃用的功能。