???? 博客主页:倔强的石头的****主页
????Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注
阅读本篇文章之前,你需要具备的前置知识:类和对象的基础
点击下方链接
【C++指南】类和对象(一):类和对象的定义和使用 基础讲解-****博客
在搞懂析构函数之前,建议阅读构造函数文章:(构造函数与析构函数配套使用)
点击下方链接:
【C++指南】类和对象(二):类的默认成员函数——全面剖析构造函数-****博客
系列后续文章:
【C++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-****博客
【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-****博客
目录
引言
析构函数的特性
默认析构函数的行为:
析构函数的规则
需要自己实现析构函数的情况:
示例代码:
实现析构函数需要考虑的问题:
结尾
引言
在C++编程中,析构函数是一个特殊的成员函数,它在对象的生命周期结束时被自动调用,用于执行清理工作,如释放对象占用的资源、关闭文件、解除动态分配的内存等。析构函数的存在确保了资源的正确管理和避免内存泄漏等问题。
本文将深入探讨C++析构函数的工作原理、特性、使用场景以及相关的最佳实践。
类似于前面的构造函数,想要掌握析构函数,也应该从这两个方面入手:
- 第⼀:我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求。
- 第⼆:编译器默认⽣成的函数不满足我们的需求,我们需要自己实现,那么如何自己实现?
析构函数的特性
-
名称:析构函数的名称必须与类名相同,但前面有一个波浪号(
~
)。例如,类MyClass
的析构函数名称为~MyClass()
。 -
无返回类型:析构函数没有返回类型,包括
void
。 -
无参数:析构函数不接受任何参数。
-
自动调用:当一个对象的生命周期结束时,析构函数会被自动调用。这包括以下几种情况:
- 局部对象离开其作用域时。
- 动态分配的对象被
delete
释放时。 - 全局或静态对象在程序结束时。
- 对象作为类的成员被销毁时(例如,当包含该对象的另一个对象被销毁时)
默认析构函数的行为:
如果类没有显式定义析构函数,编译器会生成一个默认析构函数。默认析构函数对于内置类型不做处理,对于自定义类型成员会调⽤他的析构函数·。
还需要注意的是:
我们显式写析构函数,对于⾃定义类型成员也会调用他的析构,也就是说⾃定义类 型成员⽆论什么情况都会⾃动调⽤析构函数
析构函数的规则
-
只能有一个析构函数:每个类只能有一个析构函数。
-
不能被重载:析构函数不能被重载,因为它们的名称和参数列表是固定的。这一点不同于构造函数
-
不能被显式调用:析构函数不能被显式调用(除了通过
delete
释放动态分配的对象)。它们是由编译器自动调用的。 -
对象销毁顺序:局部对象的销毁顺序与它们的创建顺序相反。全局和静态对象的销毁顺序与它们的定义顺序相反(但具体顺序在不同编译器和链接器之间可能有所不同)。
-
成员对象的析构:当一个对象被销毁时,它的成员对象(包括基类部分)的析构函数会按照它们被构造的相反顺序被调用。
需要自己实现析构函数的情况:
- 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数
- 如果默认⽣成的析构就可以用,也就不需要显式写析构,比如类中的成员变量都为自定义类型,那么默认析构函数会自动调用成员变量的析构函数
- 有资源申请时,⼀定要自己写析构,否则会造成资源泄漏
示例代码:
以下是一个简单的C++类,它包含动态分配的内存,并在析构函数中释放这些内存:
#include <iostream>
class MyClass {
private:
int* data; // 动态分配的内存
public:
// 构造函数,动态分配内存
MyClass(int size) {
data = new int[size];
std::cout << "Memory allocated for MyClass object." << std::endl;
}
// 析构函数,释放动态分配的内存
~MyClass() {
delete[] data;
std::cout << "Memory freed for MyClass object." << std::endl;
}
// 其他成员函数...
};
int main() {
MyClass obj(10); // 创建对象,分配内存
// ... 使用对象 ...
// 当obj离开作用域时,析构函数被调用,释放内存
return 0;
}
实现析构函数需要考虑的问题:
析构函数的实现通常涉及以下步骤:
- 释放动态内存:如果对象在生命周期中动态分配了内存,析构函数应该负责释放这些内存。
- 关闭文件和网络连接:如果对象持有文件句柄或网络连接,析构函数应该负责关闭它们。
- 调用成员对象的析构函数:如果对象包含其他对象作为成员,析构函数将自动调用这些成员对象的析构函数(按照成员变量在类中声明的逆序)。注意是自动调用,无需也无法主动调用
- 执行其他必要的清理操作:如解除锁、记录日志等。
结尾
C++析构函数是对象生命周期管理的重要组成部分。通过正确地实现和使用析构函数,程序员可以确保资源得到正确的释放和管理,从而避免内存泄漏和其他资源相关问题。
理解析构函数的工作原理和最佳实践对于编写健壮、可维护的C++代码至关重要。
系列后续文章:
【C++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-****博客
【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-****博客