一、什么是析构函数
在C++中,为了更好在对象被销毁时,做好清理和释放的工作,引入析构函数。
二、析构函数的特点
1、析构函数名与类名一致
2、析构函数不能构成重载,一个类只能有一个析构函数
3、析构函数无参
4、析构函数在对象被销毁时,自动调用
5、每个对象被销毁时,就调用一次析构函数
6、如果类设计者没有手动实现析构函数,编译器就会提供一个默认的析构函数,析构体为空,一经手动实现,则系统的默认函数就不复存在。
7、如果存在多个同类对象,调用析构函数顺序是最先创建的对象最后销毁,后创建的对象先销毁。
三、案例:
1、如果存在多个同类对象,调用析构函数顺序是最先创建的对象最后销毁,后创建的对象先销毁。
#include <iostream> #include <cstring> using namespace std; class Test { int a; public: Test(int a = 0) // 普通构造函数 { cout << "Test(int a = 0)" << endl; this->a = a; } Test(const Test &other) // 拷贝构造函数 { cout << "Test(const Test &other)" << endl; this->a = other.a; } void show() { cout << "a = " << a << endl; } ~Test() // 析构函数 { cout << "~Test()" << endl; show(); } }; int main() { Test A(10); // 先创建的A对象,最后销毁 Test B(100); // 后创建的B对象,先销毁 return 0; }
2、当对象作为返回值时,其调用析构函数的时间不是函数结束,而是接收这个对象的对象的销毁时间。
#include <iostream> #include <cstring> using namespace std; class Test { int a; public: Test(int a = 0) // 普通构造函数 { cout << "Test(int a = 0)" << endl; this->a = a; } Test(const Test &other) // 拷贝构造函数 { cout << "Test(const Test &other)" << endl; this->a = other.a; } void show() { cout << "a = " << a << endl; } ~Test() // 析构函数 { cout << "~Test()" << endl; show(); } }; Test func() { cout << "func start" << endl; Test B(100); cout << "func end" << endl; return B; } int main() { Test A = func(); A.show(); return 0; }
3、同一个对象可以多次调用析构函数,但最后一次是系统自动调用的。
#include <iostream> #include <cstring> using namespace std; class Test { int a; public: Test(int a = 0) // 普通构造函数 { cout << "Test(int a = 0)" << endl; this->a = a; } Test(const Test &other) // 拷贝构造函数 { cout << "Test(const Test &other)" << endl; this->a = other.a; } void show() { cout << "a = " << a << endl; } ~Test() // 析构函数 { cout << "~Test()" << endl; show(); } }; int main() { Test A(100); A.~Test(); A.~Test(); return 0; }
4、如果成员变量含有数组指针时,多次调用析构函数有可能会出错,跟编译器版本有关。
#include <iostream> #include <cstring> using namespace std; class Test { int a; char *b; public: Test(int a = 0) // 普通构造函数 { cout << "Test(int a = 0)" << endl; this->a = a; this->b = nullptr; } void setB(char *str) { b = new char[strlen(str) + 1]; strcpy(b, str); b[strlen(str)] = '\0'; } void show() { cout << "a = " << a << endl; cout << "b = " << b << endl; } ~Test() // 析构函数 { cout << "~Test()" << endl; show(); if(b) { delete[] b; b = nullptr; } } }; int main() { Test A(100); A.setB((char*)"Hello World"); A.~Test(); A.~Test(); return 0; }
四、构造函数与析构函数的异同
相同点:
1、都是类的成员函数,都会自动调用。
2、C++编译器会默认提供一个构造函数和析构函数,当手动实现其中某一个时,就不会提供那个一。
不同点:
1、构造函数可以重载,而析构函数不可重载。
2、构造函数可以有多个,而析构函数只能有一个。
3、构造函数可以无参或者有参,而析构函数只能是无参。
4、构造函数在创建类对象时调用,而析构函数在销毁类对象时调用。
五、总结
析构函数与构造函数相对应,每创建一次对象,都要调用一次构造函数,最后都要调用析构函数,释放对象。同一个对象多次调用析构函数可能会出错。