析构函数
析构函数也是一个函数
- 触发时机:在对象空间被销毁之前调用
- 作用:释放资源,销毁堆内存
1.语法
与构造函数类似,析构函数的名称要和类名相同,没有返回值,不能有参数,但是函数名前要加~
c++
#include<iostream>
using namespace std;
class Person {
public:
~Person() {
cout << "析构函数被调用" << endl;
}
};
int main() {
Person p1;
return 0;
}
我们发现,我没没有手动释放内存空间,析构函数也被执行
因为我们在栈上定义数据时,栈会自动释放内存
而在堆中定义数据时,则不会
c++
#include<iostream>
using namespace std;
class Person {
public:
~Person() {
cout << "析构函数被调用" << endl;
}
};
int main() {
Person* p1 = new Person();
return 0;
}可以看到,没有手动释放内存,析构函数并没有执行

而当我们手动通过delete把堆中数据删除时,析构函数才会执行
c++
#include<iostream>
using namespace std;
class Person {
public:
~Person() {
cout << "析构函数被调用" << endl;
}
};
int main() {
Person* p1 = new Person;
delete p1;
return 0;
}
2.释放堆空间
我们在类中声明一个指针变量,并让它指向一个堆地址
发现,当我们手动delete对象后,该变量的值依然存在
c++
#include<iostream>
using namespace std;
class Person {
public:
int* p;
~Person() {
cout << "析构函数被调用" << endl;
}
};
int main() {
Person* p1 = new Person;
p1->p = new int(10);
delete p1;
cout << *p1->p << endl; // 10
return 0;
}这时就需要发挥析构函数的作用了
我们需要在析构函数中将堆中的数据释放,把指针变成空指针,并删除地址空间
nullptr相当于NULL,意为空指针
此时当释放内存后再访问堆中的数据,便会报错了
c++
#include<iostream>
using namespace std;
class Person {
public:
int* p;
~Person() {
if (p != nullptr) {
delete p;
p = nullptr;
}
}
};
int main() {
Person* p1 = new Person;
p1->p = new int(10);
delete p1;
cout << *p1->p << endl; // 访问错误
return 0;
}