default
就是指示编译器生成一个合成版本的构造/析构函数(包括拷贝构造,赋值构造,移动构造,移动赋值构造)。
class A{
public:
A() = default;
A(const A& a) = default;
A& operator=(A&);
~A() = default;
}
我们只能对具有合成版本的成员函数使用=default;
比如你已经定义了一个有参的构造函数,那么默认构造函数编译器就不再生成了,你可以通过default关键字让默认构造函数恢复相对于 =default
delete
=delete,用于定义删除函数,在旧标准下,我们如果希望阻止拷贝可以通过显式声明拷贝
构造函数和拷贝赋值函数为private,但新标准下允许我们定义删除函数
class NoCopy{
NoCopy() = default;
NoCopy(const NoCopy&) = delete; // 阻止拷贝
NoCopy& operator=(const NoCopy&) = delete; //阻止赋值
~NoCopy() = default;
}
- =delete必须出现在函数第一次声明的时候。
- =delete可以使用在任意的函数上(可以引导函数匹配过程),除了析构函数(析构函数为删除函数将导致该类型无法销毁)
iostream类阻止了拷贝,避免多个对象同时写入,或读取相同的IO缓冲,我们可以将拷贝构造函数和拷贝赋值运算符定义为删除的函数来阻止拷贝,虽然声明了他们,但不能以任何的方式使用他们,在参数列表之后加上 =delete 来指出我们希望其是被删除的,这是为了通知编译器,我们不希望这些函数被定义
析构函数不能是删除函数
对于删除析构函数的类型,虽然我们不能定义这种类型的变量或成员,但可以动态分配这种而理性的对象,但是不能释放这些对象。
合成的拷贝控制成员可能是删除的
- 如果类的某个成员的析构函数是删除的或者不可访问的,则类的合成析构函数被定义为删除的。
解释:类的某个成员的析构函数是删除的或不可访问的,那么这个成员是不可删除的,当然这个类的对象也是不可删除的了。 - 如果类的某个成员的拷贝构造函数是删除的或者不可访问的,那么类的合成拷贝构造函数被定义为删除的。如果类的某个成员的析构函数是删除的或者不可访问的,则类合成的拷贝构造函数也是被定义为删除的。
解释:类的某个成员的拷贝构造函数是删除的或者不可访问的,那么说明类的这个成员的拷贝构造函数是无法调用的,那么这个类的拷贝构造函数当然是不可访问的。因为类的拷贝构造函数会调用类的成员的拷贝构造函数。 - 如果类有一个const的或引用成员,则类的合成拷贝赋值运算符被定义为删除的。
解释:这条记住就可以了。但是,如果这个const或者引用成员有一个类内初始值,另当别论,拷贝构造函数完全可以是正常的。 - 如果类的某个成员的析构函数是删除的或不可访问的,或是类有一个引用成员,它没有类内初始化器,或是类有一个const成员,它没有类内初始化器且其类型未显式定义默认构造函数,则该类的合成的默认构造函数被定义为删除的。
本质上,当不可能拷贝、赋值、销毁类的成员时,类的拷贝构造函数会被定义为删除的