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

时间:2014-11-01 08:23:03

标签: c++ constructor language-lawyer rule-of-three

12.8 / 7节中的标准说:

  

如果类定义未明确声明副本   构造函数,一个是隐式声明的。如果是类定义   声明一个移动构造函数或移动赋值运算符   隐式声明的复制构造函数被定义为已删除;除此以外,   它被定义为默认值(8.4)。 如果,则不推荐使用后一种情况   类具有用户声明的复制赋值运算符或用户声明的   。因此,对于类定义

struct X {
    X(const X&, int);
};
     

隐式声明了复制构造函数。如果是用户声明的   构造函数后来被定义为

X::X(const X& x, int i =0) { /∗ ... ∗/ }

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

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

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

int main(){ }

DEMO

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

我想如果我们写下以下内容:

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

A a;

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

int main()
{ 

}

DEMO

复制构造函数未被明确删除。但事实并非如此。

2 个答案:

答案 0 :(得分:4)

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

  

在示例中,标准既不提供复制分配也不提供   析构函数是用户十进制的。

该示例与弃用无关。

  

我已经尝试过这样做:[...]但在示例中我们仍然有隐含声明的副本   构造

您无法定义隐式声明的复制构造函数 - 因为它已经由= default定义(没有双关语)。你必须先自己申报。

  

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

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

  

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

显然,

A(const A&&){ }

是[class.copy] / 3的移动构造函数。如果您删除了此移动构造函数,则your example compiles,尽管它使用了所述已弃用的功能。

答案 1 :(得分:1)

贬值通常意味着某些东西会起作用,但它是不受欢迎的,并且可能在将来不起作用。我认为标准是说如果你创建一个用户声明的复制赋值运算符或用户声明的析构函数,它仍然会创建一个默认的复制构造函数(如果你还没有) - 但它将来可能不会。所以他们希望你现在创建自己的复制构造函数,如果你有其他两个中的一个,将来他们可能会强迫你。