首页 > 编程笔记

C++析构函数详解

C++ 提供了一系列用于资源管理和对象生命周期控制的机制,其中析构函数(Destructor)就是一个重要的部分。

在 C++ 中,创建对象的时候会调用构造函数,相应地在释放对象的时候会调用析构函数。同构造函数一样,析构函数也是类中一个特殊的成员函数,并且也是由编译器自动调用的。

虽然很多初学者可能觉得析构函数不常用,但了解其工作原理与应用场景是深入理解 C++ 的关键。本节重点介绍析构函数的定义和使用。

析构函数的定义

和构造函数相反,当类对象脱离它的作用域时(例如对象所在的函数已调用完毕),编译器会自动执行析构函数。

析构函数通常用来做“清理善后”的工作,例如在建立对象时用 new 开辟了一片内存空间,对象被销毁时应手动用 delete 释放,释放的工作就可以放在析构函数里。

析构函数的名称和类名相同,但前面加有波浪号~。与构造函数相反,析构函数没有参数,也不能被重载。

例如:
class MyClass {
public:
    // 构造函数
    MyClass() {
        // 分配资源
    }
   
    // 析构函数
    ~MyClass() {
        // 释放资源
    }
};
如果不在类中手动定义析构函数,那么编译器也会自动添加一个析构函数,不过这个由编译器添加的析构函数不进行任何操作。因此,如果有一些需要自己去释放的东西,比如释放堆空间、关闭文件句柄等,就一定要手动定义析构函数。

使用析构函数时,还需要注意以下两点:

完整实例

下面的实例演示了一个名为 Person 的简单类,该类动态分配一个字符数组来存储名字,并在析构函数中释放这个数组。
#include <iostream>
#include <cstring>

class Person {
public:
    // 构造函数
    Person(const char* name) {
        this->name = new char[strlen(name) + 1];
        strcpy(this->name, name);
        std::cout << name << " is born!" << std::endl;
    }

    // 析构函数
    ~Person() {
        std::cout << name << " is gone!" << std::endl;
        delete[] name;
    }

private:
    char* name;
};

int main() {
    {
        Person p1("Alice");
        Person p2("Bob");
    } // p1 和 p2 的析构函数在这里调用

    Person* p3 = new Person("Charlie");
    delete p3; // p3 的析构函数在这里调用

    return 0;
}
输出结果为:

Alice is born!
Bob is born!
Bob is gone!
Alice is gone!
Charlie is born!
Charlie is gone!

示例中创建了 3 个 Person 对象,因此会调用 3 次构造函数,相应地也会调用 3 次析构函数。

推荐阅读