前言:
构造函数 和 析构函数是每个类都有的东西,但是经常见到的东西未必就是我们深刻了解的,相反这些内容更有可能成为隐藏很深的不稳定因素。
构造函数:
构造函数初始化非static成员变量,然后再做一些其他自定义动作。
构造会对成员变量挨个构造,如果是内置类型则使用默认值,如果是类类型,则使用默认构造函数,如果某个成员变量没有默认构造函数,则编译是会报错。
析构函数:
析构函数销毁所有非static成员变量(自定义类类型的成员变量,内置类型会自动释放),其实就是调用成员变量的析构(如果有析构的话,内置类型就自动释放),然后做一些自定义动作。
析构则挨个析构成员变量,如果类中保存了一个指针成员变量,那么析构时只会析构这个指针(智能指针是类,因此也会被析构,这同时会伴随着引用计数的减少),而不会析构指针指向的内容。因此,在使用指针时,务必注意是否指向了new出来的内存,如果是,这部分内存有没有什么 地方会释放它,如果没有,那么请在析构函数中手动释放。
上面提到了可能需要手动delete指针类型的成员变量,这个动作是有风险的,因为这个指针指向的内存可能别的实例也持有,这就可能存在重复释放相同内存的风险。这里可以使用智能指针来完成内存的释放。
如果一个类需要自定义析构函数,那么根据经验判断,这个类肯定需要 自定义 拷贝构造 和 重载赋值。
注:这里说的重载赋值是很多书上说的赋值构造,这里之所以称之为重载赋值见
原因:
某个类有指针类型的数据成员,指向new出来的内存。那么这个类必须要在析构函数中delete这个指针。那么,如果使用默认拷贝构造会怎么样,此时这个指针会被复制,此时就有多个指针指向相同的动态内存区,当其中一个实例在析构中释放动态内存区是,其他实例的指针将变为野指针。因此,需要自定义拷贝构造和拷贝赋值,在其中,将指针赋值换成创建新对象,然后再赋值给指针。
=default补充:
只能对具有合成版本的函数使用 =default ,=default是要求编译器为我们生成默认版本的函数,如果这个函数都没有合成版本(由编译器生成),那么=default告诉编译器,编译器才不鸟你,直接报错。