「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
💦 概念
前面通过构造函数的学习,我们知道一个对象时怎么来的,那一个对象又是怎么没呢的 ???
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
class Date
{
public:
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
~Date()
{
cout << "~Date()" << endl;//证明我来过
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
return 0;
}
📝 说明
像 Date 这样的类是不需要析构函数的,因为它内部没有什么资源需要清理
💦 特性
析构函数是特殊的成员函数。
其特征如下:
1️⃣ 析构函数名是在类名前加上字符 ~。
2️⃣ 无参数无返回值 (不支持重载)。
3️⃣ 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4️⃣ 对象生命周期结束时,C++ 编译系统系统自动调用析构函数。
❓ 析构函数有什么意义 ❔
析构函数具体有什么意义要看具体是什么类,哪些类的析构函数是有意义的呢 ❓
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int)*capacity);
if(_a == nullptr)
{
cout << "malloc fail" << endl;
exit(-1);
}
_top = 0;
_capacity = capacity;
}
~Stack()
{
free(_a);
_a = nullptr;
}
private:
int* _a;
int _top;
int _capacity;
};
int main()
{
Stack st;
return 0;
}
📝 说明
在之前我们写栈时都需要写一个 Destroy 在程序结束前销毁动态开辟的内存,很多童鞋可能在使用完动态开辟的内存没有 Destroy 导致后面的一些内存泄漏的操作。而析构函数的出现就是为了解决这种场景的,对象实例化后,同构造函数一样,它不需要我们主动调用,它是在对象生命周期结束后自动调用,注意析构函数没有参数所以不能重载。
构造函数是为了替代 Init,析构函数是为了替代 Destroy。
一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数 ❓
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int)*capacity);
if(_a == nullptr)
{
cout << "malloc fail" << endl;
exit(-1);
}
_top = 0;
_capacity = capacity;
}
private:
int* _a;
int _top;
int _capacity;
};
int main()
{
Stack st;
return 0;
}
📝 说明
与构造函数类似,我们不写,编译器默认生成的构造函数也会做偏心的处理
1、内置类型成员不处理 2、自定义类型成员会去调用它的析构函数
为什么内置类型不处理 ❓
因为它不好处理,如果这个指针是一个文件指针,那你也要去 free 吗 ???
那对于什么样的类可以不写析构呢或者它的价值是什么 ❓
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int)*capacity);
if(_a == nullptr)
{
cout << "malloc fail" << endl;
exit(-1);
}
_top = 0;
_capacity = capacity;
}
~Stack()
{
free(_a);
_a = nullptr;
}
private:
int* _a;
int _top;
int _capacity;
};
class MyQueue
{
private:
Stack _pushST;
Stack _popST;
};
int main()
{
MyQueue mq;
return 0;
}
📝 说明
这是之前的一个题 —— 两个栈实现队列
现在对于 MyQueue,我们可以不写构造函数和析构函数,让编译器自动生成构造函数和析构函数也可以 Init 和 Destroy,具体如下:
1、初始化 _pushST 和 _popST
2、销毁 _pushST 和 _popST
💨 由以上就可以看出编译器默认生成的析构函数也是有价值的