C++ 析构函数

1、析构函数

析构函数,其实就是构造函数的相反操作,构造函数是创建对象时候,用来给对象的成员数据赋值的,而析构函数是用了清理对象的。


2、析构函数的特点

①析构函数就是位取反运算符+类名表示。

②构造函数可以有多个,而析构函数只能有一个,不可重载,不能有参数。

③与构造函数相同,析构函数没有返回值。如果没有显式写出析构函数,编译器会自动加上一个默认的析构函数,如果写了的话,就不会再加。

#include<bits/stdc++.h>
using namespace std;
class Point{
    public:
        Point(double xx=0.0,double yy=0.0);
        ~Point();
        void get();
    private:
        double x,y;
};
Point::Point(double xx,double yy):x(xx),y(yy){
}
Point::~Point(){
    cout<<"end"<<endl;
}
void Point::get(){
    cout<<"x="<<x<<"  y="<<y<<endl;
}
int main(){
    Point a(5.0,6.0);
    a.get();
    return 0;
}

3、析构函数被调用的情况

①对象的生命周期结束。(比如在函数中的声明 函数结束前会调用)

void fun(){
    Point a(5.0,6.0);
}
int main(){
    fun();
    return 0;
}

②如果对象是new出来的,用delete释放空间时候会调用。不手动delete是不会调用析构函数的。

int main(){
    Point *a=new Point(6.0,7.0);
    delete a;
    return 0;
}

③对象a是对象b的成员,对象b的析构函数被调用时候,对象a的析构函数也会被调用。

#include<bits/stdc++.h>
using namespace std;
class Point{
    public:
        Point(double xx=0.0,double yy=0.0);
        ~Point();
        void get();
    private:
        double x,y;
};
Point::Point(double xx,double yy):x(xx),y(yy){
}
Point::~Point(){
    cout<<"Point end"<<endl;
}
void Point::get(){
    cout<<"x="<<x<<"  y="<<y<<endl;
}

class Line{
    public:
        Line();
        ~Line();
    private:
        Point point;
};
Line::Line(){
}
Line::~Line(){
    cout<<"Line end"<<endl;
}

class test{
    public:
        test();
        ~test();
    private:
        Line line;
};
test::test(){
}
test::~test(){
    cout<<"test end"<<endl;
}
int main(){
    test A;
    return 0;
}

4、总结

析构函数不仅仅是用来清理对象释放内存的,也可以是在析构函数中编写在清理对象前需要做的一些工作。

### C++ 析构函数的使用方法 析构函数是在对象生命周期结束时自动调用的一个特殊成员函数,用于执行清理操作。它的功能主要包括释放动态分配的内存、关闭打开的文件以及释放其他资源等[^3]。 #### 定义方式 析构函数的名字由波浪号 `~` 加上类名组成,不接受任何参数也不返回任何值。例如: ```cpp class MyClass { public: ~MyClass(); // 析构函数声明 }; // 析构函数定义 MyClass::~MyClass() { // 清理逻辑 } ``` 如果未显式定义析构函数,则编译器会自动生成一个默认析构函数[^1]。默认析构函数通常适用于简单的数据结构,但对于复杂的数据结构(如包含动态分配的内存),则需要手动定义以确保资源被正确释放。 --- ### 默认析构函数与用户定义析构函数的区别 - **默认析构函数**: 编译器生成的默认析构函数仅负责销毁类中的非静态成员变量,并不会处理额外的清理任务。它适合于那些不需要特别清理工作的简单类[^4]。 - **用户定义析构函数**: 当类中存在动态分配的资源(如堆内存、文件句柄或其他外部资源)时,必须显式定义析构函数来完成这些资源的释放。例如: ```cpp class ResourceHandler { private: int* data; public: ResourceHandler(int size) : data(new int[size]) {} // 动态分配内存 ~ResourceHandler() { delete[] data; } // 显式释放内存 }; ``` 在此例子中,如果没有显式的析构函数,`data` 所指向的堆内存将无法得到释放,从而引发内存泄漏问题。 --- ### 需要显式定义析构函数的情况 以下是几种常见的场景,其中需要显式定义析构函数而不是依赖默认版本: 1. 类中有动态分配的内存; 2. 类管理了某些外部资源(如文件流、数据库连接等); 3. 存在继承关系且基类拥有虚函数的情况下,为了支持多态行为,应将基类的析构函数声明为虚拟函数。 示例代码如下所示: ```cpp class Base { public: virtual ~Base() {} // 虚拟析构函数 }; class Derived : public Base { public: ~Derived() override {} // 派生类析构函数 }; ``` --- ### 私有析构函数的应用 有时出于设计需求,可能希望限制某个类的对象只能通过特定的方式创建或销毁。此时可以通过将析构函数设为私有并提供友元函数或者嵌套类来进行间接访问[^2]。然而需要注意的是,在这种模式下容易遇到一些潜在风险,比如内存泄漏和继承相关的问题。 --- ### 注意事项 编写析构函数时需注意以下几点以保障程序的安全性和效率: 1. **避免重复删除同一块内存**:多次调用 `delete` 或者错误地释放已经释放过的指针可能导致未定义行为。 2. **防止异常抛出**:由于析构函数本身不应该失败,因此在其内部尽量减少可能会触发异常的操作。 3. **考虑线程安全因素**:对于共享资源而言,析构过程中应当同步多个线程之间的交互以防竞争条件发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会c语言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值