【C++指南】类和对象(三):类的默认成员函数——全面剖析: 析构函数

倔强的石头_ 2024-10-15 09:35:03 阅读 70

     💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:《C++指南》

                                  期待您的关注

 

47f09392526c71b5885ec838a3ea7ffe.gif

 

阅读本篇文章之前,你需要具备的前置知识:类和对象的基础

点击下方链接

【C++指南】类和对象(一):类和对象的定义和使用 基础讲解-CSDN博客

在搞懂析构函数之前,建议阅读构造函数文章:(构造函数与析构函数配套使用)

点击下方链接:

 【C++指南】类和对象(二):类的默认成员函数——全面剖析构造函数-CSDN博客

 系列后续文章:

【C++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-CSDN博客

【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-CSDN博客

 

目录

引言

析构函数的特性

默认析构函数的行为:

析构函数的规则

需要自己实现析构函数的情况:

示例代码:

实现析构函数需要考虑的问题:

结尾


 

 

引言

在C++编程中,析构函数是一个特殊的成员函数,它在对象的生命周期结束时被自动调用,用于执行清理工作,如释放对象占用的资源、关闭文件、解除动态分配的内存等。析构函数的存在确保了资源的正确管理和避免内存泄漏等问题。

本文将深入探讨C++析构函数的工作原理、特性、使用场景以及相关的最佳实践。

类似于前面的构造函数,想要掌握析构函数,也应该从这两个方面入手

第⼀:我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求。第⼆:编译器默认⽣成的函数不满足我们的需求,我们需要自己实现,那么如何自己实现

 

 

析构函数的特性

名称:析构函数的名称必须与类名相同,但前面有一个波浪号(<code>~)。例如,类 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++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-CSDN博客

【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-CSDN博客

 

 

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。