[C++系列] 18. 析构函数

1. 概念

前面通过构造函数的学习,我们知道一个对象时怎么来的,那一个对象又是怎么没呢的?

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

构造函数不是去申请空间一样,析构函数也不是去释放空间,而是完成资源清理工作,即在栈上定义的对象都是编译器来帮助释放而不是析构函数来释放。

什么是清理?首先需要搞清楚那些成员是属于对象的,那些成员是不属于对象的,针对那些不属于对象的就是清理。

class A {
public:
	A(int sz = 10) {
		_pi = (int*)malloc(sizeof(int)*sz);
	}
	~A() {
		if (_pi) {
			free(_pi);
			_pi = nullptr;
		}
	}
private:
	int* _pi;
};

int main() {
	A a(20);
	system("pause");
	return 0;
}

 主函数中申请了20个int类型大小连续的空间,首先实例化时会调构造函数,调完之后,主函数执行完毕会自动调用析构函数,由于在创建对象的时候申请了一片20大小的连续空间,此时析构函数就会完成这片空间的清理工作,释放已申请的资源,但是这个时候A对象并没有被析构函数销毁,这并不是析构函数干的事情,而是编译器该干的事情。也就是目前对象的成员指针仍然存在,只有当程序执行完毕后,编译器去销毁这个对象,将这片的空间也释放。对于这个对象来讲,它里面存放的只有int类型指针,它只占4个字节的大小。而刚申请的20个整形的连续空间它是资源,不属于这个对象,是由析构函数帮助清理资源,而对象的销毁由编译器来操作。

2. 特性

析构函数是特殊的成员函数。
其特征如下:

1)析构函数名是在类名前加上字符 ~。

2)无参数无返回值。

3)一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。

4)对象生命周期结束时,C++编译系统系统自动调用析构函数。

5)关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对会自定类型成员调用它的析构函数。

class String {
public:
    String(const char* str = "jack") {
        _str = (char*)malloc(strlen(str) + 1);
        strcpy(_str, str);
    }
 
    ~String() {
        cout << "~String()" << endl;
        free(_str);
    }
private:
    char* _str;
};
 
class Person {
private:
    String _name;
    int    _age;
};
 
int main() {
    Person p;
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/88842506