文章目录
- 析构函数
- 析构函数的定义
- 析构函数的作用
- 主要作用
- 次要作用
- 析构函数的特点
- 拷贝构造函数
- 拷贝构造函数的定义
- 拷贝构造函数的作用
- 主要作用
- 次要作用
- 拷贝构造函数的特点
- 浅拷贝和深拷贝
- 浅拷贝
- 深拷贝
- 拷贝构造函数的调用场景
析构函数
析构函数的定义
析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统
自动
执行析构函数。
析构函数往往用来做“清理善后” 的工作(例如:在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
来自百度百科
析构函数的作用
主要作用
完成对 对象 申请来的资源
的清理
工作
析构函数可以用于释放对象在使用过程中分配的资源,如动态分配的内存
、打开的文件句柄
、网络连接
等
这样可以避免资源泄漏,确保程序的稳定性和资源的有效管理
次要作用
可以根据析构函数在对象生命周期结束时编译器自动调用
这个特点,在析构函数中完成一些特殊操作
【例如:在类里创建一个static修饰的成员变量,让它在调用构造函数时++,调用拷贝构造时++,调用析构函数时- -,这样就可以实时记录还有多少个“存活”】
析构函数的特点
-
析构函数名是在类名前加上字符 。
-
析构函数
没有
参数也返回值类型。 -
对象
生命周期结束时
编译器自动调用
析构函数 -
因为析构函数
没有参数
,所以析构函数不能重载
,所以一个类只有一个
析构函数 -
如果没有显式实现析构函数,编译器会
自动生成
一个默认的析构函数
这个默认的析构函数的特点是:
1 对内置类型成员变量不做处理
【无论内置类型是否申请了资源,都不处理】
2 对自定义类型 就自动调用
它所属的类的
析构函数
例
拷贝构造函数
拷贝构造函数的定义
拷贝构造函数是C++中一种构造函数的重载,它的作用是:用已有对象创建一个新对象,并将已存在的同类对象的数据成员拷贝到新对象中。
拷贝构造函数的形参是一个对该已有对象的引用,并且通常会被声明为const,以防止通过引用修改原对象
拷贝构造函数的作用
主要作用
用已有对象创建一个新对象,并将已存在的同类对象的数据成员拷贝到新对象中。
次要作用
可以根据拷贝构造函数在创建对象时编译器自动调用
这个特点,在析构函数中完成一些特殊操作
【例如:在类里创建一个static
修饰的成员变量,让它在调用构造函数时++,调用拷贝构造时++,调用析构函数时- -,这样就可以实时记录还有多少个“存活”】
拷贝构造函数的特点
-
拷贝构造函数
是构造函数的重载
,所以它也是构造函数,它只能用于创建新对象
,不能用于两个已经创建对象
之间的拷贝 -
拷贝构造函数
只有一个参数
,参数必须是该类的对象的引用
如果第不是
该类的对象的引用或者有多个参数,那它就不是拷贝构造,而是普通构造函数 -
拷贝构造的第一个参数必须是该类对象的
引用
,不能是该类对象本身
因为传值调用时,形参是实参的临时拷贝
,所以规定了传对象本身的时候要调用拷贝构造函数
这样的话,如果一个类的拷贝构造的参数是该类对象本身,那么调用拷贝构造,就要向传参,而传对象本身的时候又要调用拷贝构造,调用拷贝构造又要先传参数………
就会无穷递归
例
-
如果
没有显式
的写出拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数
这个默认的拷贝构造函数的特点是:
1,对内置类型【int char等】成员直接浅拷贝
2,对自定义类型【class,struct等】成员就调用该自定义类型自己的拷贝构造
浅拷贝和深拷贝
浅拷贝
把一个对象中的成员中存储的值
直接拷贝给另一个对象的对应成员就是浅拷贝
例
下图就是一个浅拷贝的拷贝构造函数
浅拷贝的缺点:
如果对象的成员申请了资源,那么成员中存储的往往是那片资源的地址
此时如果使用浅拷贝,就直接把这个成员中存储的地址给了另一个对象的成员,那么这两个对象的成员就会指向同一片资源,这样不仅使用不方便,析构释放资源的时候还会多次释放
,导致程序崩溃
例
上图相当于
解决办法也很简单,就让两个对象指向的资源不是同一片就可以了,也就是深拷贝
深拷贝
当对象有成员指向资源
的时候,如果要把这个对象拷贝给其他对象就要用深拷贝
深拷贝很简单,分2步
-
先“拷贝”指向资源的
数据结构
:
即如果成语指向的资源是一条节点都在堆区的链表,这个时候接受拷贝的对象的成员就也要在堆区申请空间,创建节点,制造出于那条链表相同的节点个数和节点大小 -
再拷贝数据
即把指向资源中存储的有效数据拷贝个另一个成员
例 上面例举的浅拷贝时的问题就可以这样解决
拷贝构造函数的调用场景
-
使用
已经创建好的对象
去创建新的对象
-
函数的参数类型是类的对象
因为形参是实参的临时拷贝,所以当参数是类的对象的时候,就要创建一个对象作为形参,当调用该函数的时候,编译器自动调用
拷贝构造
例
3.函数的返回值是类的对象
因为在函数调用结束后函数的栈区内存会被回收,如果返回的是在函数内创建的对象,函数调用结束后,这个对象的生命周期也会结束,空间会被释放
为了防止这样的情况,就需要创建一个临时对象来存储可能被销毁的对象的数据,这个临时对象就要编译器自动调用
拷贝构造函数创建