在C++的类中,有四类特殊的成员函数:① 默认构造函数;② 拷贝构造函数;③ 拷贝赋值函数(operator=);④ 析构函数;它们控制着类的实例的创建、初始化、拷贝以及销毁。
(1)默认构造函数:如果对构造函数进行了重载,则编译器不会隐式的生成一个默认的构造函数,此时如果调用了默认构造函数会在编译时报错,为了避免这种情况,一般会选择重写默认构造函数,且函数体为空。关键字 =default 优化了这种行为,用该关键字标记重写的默认拷贝构造函数,编译器会隐式生成一个版本,在代码更加简洁的同时,编译器隐式生成的版本的执行效率更高。
class Mine
{
public:
// 重载构造函数,此时不会隐式生成默认构造函数
Mine(int num) {}
// 可选择重写默认构造函数
Mine() {}
// 关键字 =default 标记编译器隐式生成该类的默认构造函数,
// 代码更简洁,且隐式生成的版本执行效率更高
Mine() = default;
};
int main()
{
// 调用默认构造函数
Mine ob;
// 调用默认拷贝构造函数
Mine pOb(ob);
// 需要特别注意的是:因为tOb是在创建时被赋值的,
// 所以此处的赋值操作符调用的是默认拷贝构造函数
Mine tOb = pOb;
Mine sOb;
// 在构造完成之后,赋值操作符执行的就是赋值运算了,
// 所以此时调用的就是拷贝赋值函数
sOb = tOb;
/** 离开作用域时自动调用默认的析构函数 */
return 0;
}
(2)拷贝构造函数 和 拷贝赋值函数:不论有没有对它们进行重载,编译器始终会隐式生成默认版本,但有的时候不希望类实例进行拷贝构造或拷贝赋值,此时可以重写它们并将权限设置为private,但这样只是利用语法特性来碰巧实现效果,且对友元会带来困惑。可以使用关键字 =delete 标记不想被类实例调用的拷贝构造和拷贝赋值,相当于删除了它们:
class Mine
{
public:
// 保证重载了构造函数后,编译器会隐式生成一个默认版本
Mine() = default;
Mine(Mine& ob) = delete;
Mine& operator=(Mine& ob) = delete;
};
int main()
{
Mine ob
// 编译错误,调用的拷贝构造函数已删除
Mine pOb(ob);
// 编译错误,调用的拷贝构造函数已删除
Mine tOb = pOb;
Mine sOb;
// 编译错误,调用的拷贝赋值函数已删除
sOb = tOb;
return 0;
}
(3)析构函数:一个类中有且仅有一个析构函数(所以=delete不能用于析构函数),它是一个无参无返回值且不能被重载的特殊成员函数,由系统自动调用,析构函数如果被重写,则系统会调用重写的版本,否则调用隐式生成的默认版本:
class Mine
{
public:
~Mine() {} // 显示定义,相当于重写,若没有,则调用编译器默认生成的版本
~Mine(int) {} // 编译错误,析构函数不允许被重载
~Mine() = delete; // 编译错误,类仅有一个析构函数,删除了析构怎么销毁对象
};