如果该类包含用户声明的析构函数,则复制构造函数是什么? [英] What's with the copy-constructor if the class contains a user-declared destructor?

查看:396
本文介绍了如果该类包含用户声明的析构函数,则复制构造函数是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第12.8/7节中的标准说:

如果类定义未明确声明副本 构造函数,一个隐式声明.如果类定义 声明移动构造函数或移动赋值运算符, 隐式声明的副本构造函数定义为删除;否则, 它被定义为默认值(8.4). 如果不赞成使用后一种情况 类具有用户声明的副本分配运算符或用户声明的 析构函数.因此,对于类定义

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

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

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

我无法理解如果该类具有用户声明的副本分配运算符或用户声明的析构函数,则不赞成使用后一种情况.在该示例中,Standard均未提供用户声明的副本分配运算符或析构函数.如果我们声明一个析构函数或一个拷贝赋值运算符,将会发生什么?我尝试这样做,如下所示:

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

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

int main(){ }

演示

,但是在示例中,我们仍然具有隐式声明的副本构造函数.该规则的实际含义是什么?

我认为如果我们编写以下内容:

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

A a;

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

int main()
{ 

}

演示

复制构造函数不会被明确删除.但是事实并非如此.

解决方案

此弃用基本上包含了三(五)规则".如果提供了用户声明的副本分配运算符或析构函数,则不赞成将副本构造函数定义为默认(而不是删除)的事实.那应该避免您将来再依赖这种隐式声明的副本构造函数.

在该示例中,标准既未提供副本分配也未提供 析构函数是用户定义的.

该示例与弃用无关.

我尝试如下操作:[…]但在示例中,我们仍然具有隐式声明的副本 构造函数.

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

我认为,如果我们写以下内容:[…]复制构造函数将不会被明确删除.但这不是真的.

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

如果类定义声明了move构造函数或move 赋值运算符,隐式声明的副本构造函数为 定义为已删除;

很明显

A(const A&&){ }

是根据[class.copy]/3的move构造函数.如果您删除了此move构造函数,则尽管它使用了已弃用的功能,但您的示例会编译. /p>

The Standard in section 12.8/7 says:

If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. Thus, for the class definition

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

a copy constructor is implicitly-declared. If the user-declared constructor is later defined as

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

I can't get the point of that The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. In the example the Standard neither provides a user-declared copy assignment operator nor a destructor. What will happen if we declare a destructor or a copy assignment operator? I've tried to do that as follows:

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

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

int main(){ }

DEMO

but in the example we still have the implicitly-declared copy constructor. What does that rule actual mean?

I thought that if we write the following:

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

A a;

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

int main()
{ 

}

DEMO

the copy-constructor won't explicitly deleted. But thats's not the case.

解决方案

This deprecation basically incorporates the Rule of Three (Five). If a user-declared copy assignment operator or destructor is provided, the fact that the copy constructor is defined as defaulted (and not as deleted) is deprecated. That should prevent you from depending upon such an implicitly declared copy constructor in future.

In the example the Standard provides neither copy assignment nor destructor are user-decalred.

The example has nothing to do with the deprecation.

I've tryied to do that as follows: […] but in the example we still have the impliclty-declared copy constructor.

You cannot define an implicitly declared copy constructor - because it's already defined, by = default (no pun intended). You would have to declare it yourself first.

I thought that If we wirte the following: […] the copy-constructor won't explicitly deleted. But it's not true.

You quoted the rule that explicitly specifies that the copy constructor will be implicitly defined as deleted if a move constructor is declared:

If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted;

Clearly,

A(const A&&){ }

Is a move constructor according to [class.copy]/3. If you removed this move constructor then your example compiles, although it uses said deprecated feature.

这篇关于如果该类包含用户声明的析构函数,则复制构造函数是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆