C++深度解析(14)—对象的销毁

it2022-05-05  93

1.对象的销毁

一般而言,需要销毁的对象都应该做清理 解决方案:  为每个类都提供—个public的free函数 对象不再需要时立即调用free函数进行清理 class Test    {       int* p;   public:       Test()       {           p = new int;       }        void free()       {           delete p       }    };   存在的问题  free只是—个普通的函数,必须显示的调用 对象销毁前没有做清理,很可能造成资源泄漏 C++编译器是否能够自动调用某个特殊的函数进行对象的清理?

2.析构函数

 C++的类中可以定义—个特殊的清理函数  这个特殊的清理函数叫做析构函数 析构函数的功能与构造函数相反 定义: ~ClassName()  析构函数没有参数也没有返回值类型声明 析构函数在对象销毁时自动被调用  #include <stdio.h> class Test { private: int mI; public: Test(int i) : mI(i) { printf("Test(), mI = %d\n", mI); } ~Test() { printf("~Test(), mI = %d\n", mI); } }; void run() { Test t1(1); Test t2(2); } int main() { run(); // 函数返回前,t1,t2自动调用析构函数 printf("Press any key to continue..."); getchar(); return 0; } 运行结果:

3.数组类的进化

Array.h #ifndef _ARRAY_H_ #define _ARRAY_H_ class Array { private: int mLength; int* mSpace; public: Array(int length); Array(const Array& obj); int length(); void setData(int index, int value); int getData(int index); ~Array(); }; #endif Array.cpp #include "Array.h" Array::Array(int length) { if( length < 0 ) { length = 0; } mLength = length; mSpace = new int[mLength]; } Array::Array(const Array& obj) { mLength = obj.mLength; mSpace = new int[mLength]; for(int i=0; i<mLength; i++) { mSpace[i] = obj.mSpace[i]; } } int Array::length() { return mLength; } void Array::setData(int index, int value) { mSpace[index] = value; } int Array::getData(int index) { return mSpace[index]; } Array::~Array() { mLength = -1; delete[] mSpace; } main.cpp #include <stdio.h> #include "Array.h" int main() { Array a1(10); for(int i=0; i<a1.length(); i++) { a1.setData(i, i); } for(int i=0; i<a1.length(); i++) { printf("Element %d: %d\n", i, a1.getData(i)); } Array a2 = a1; for(int i=0; i<a2.length(); i++) { printf("Element %d: %d\n", i, a2.getData(i)); } printf("Press any key to continue..."); getchar(); return 0; }

4.析构函数的定义准则 

当类中自定义了构造函数,并且构造函数中使用了系统资源(如:内存申请,文件打开,等),则需要自定义析构函数。

5.构造和析构顺序

当类中有成员变量是其它类的对象时 首先调用成员变量的构造函数,调用顺序与声明顺序相同 之后调用自身类的构造函数 析构函数的调用秩序与对应的构造函数调用秩序相反 #include<stdio.h> class Member { const char *ms; public: Member(const char *s) { printf("Member(const char *s): %s\n", s); ms = s; } ~Member() { printf("~Member():%s\n", ms); } }; class Test { Member mA; Member mB; public: Test(): mB("mB"),mA("mA") { printf("Test()\n"); } ~Test() { printf("~Test()\n"); } }; Member *pt = new Member("gA"); void run() { Test t; } int main() { run(); delete pt; getchar(); return 0; } 运行结果:关于析构的答案  对于栈对象和全局对象,类似于入栈与出栈的顺序,最后构造的对象被最先析构!堆对象的析构发生在使用delete的时候,与delete的使用顺序相关!​​​​​​ps:运行时看不到析构函数打印:析构函数,是编译器认为需要析构就析构,不受程序员的直接控制。但是也有一些技巧,可以利用比如: 1)动态分配的内存构造成功的话,delete 就会及时析构2)自动变量,语句组的大括号内(构造成功的话)遇到结束的大括号,一定会析构。另外,没有构造成功的对象,是不会析构的。

6.小结

析构函数是C++中对象销毁时做清理工作的特殊函数析构函数在对象销毁时自动被调用析构函数是对象所使用的资源及时释放的保障析构函数的调用秩序与构造函数相反

最新回复(0)