首页 > 编程笔记

C++析构函数的定义和使用

创建对象时,系统会为对象分配所需要的内存空间等资源,当程序结束或对象被释放时,系统为对象分配的资源也需要回收,以便可以重新分配给其他对象使用。

在 C++ 中,对象资源的释放通过析构函数完成。

析构函数的作用是在对象被释放之前完成一些清理工作。析构函数调用完成之后,对象占用的资源也被释放。

与构造函数一样,析构函数也是类的一个特殊成员函数,其定义格式如下所示:

class 类名
{
    ~析构函数名称();
    ...   //其他成员
}

关于析构函数的定义,有以下注意事项:

析构函数的调用情况主要有以下几种:
注意:析构函数的调用顺序与构造函数的调用顺序是相反的。在构造对象和析构对象时,C++ 遵循的原则是:先构造的后析构,后构造的先析构

例如,连续创建了两个对象 A1 和 A2,在创建时,先调用构造函数构造对象 A1,再调用构造函数构造对象 A2;

在析构时,先调用析构函数析构对象 A2,再调用析构函数析构对象 A1。

示例

下面通过案例演示析构函数的定义与调用,C++ 代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Rabbit        //定义兔子类Rabbit
{
public:
    Rabbit(string name,const char* pf);  //声明构造函数
    void eat();
    ~Rabbit();        //声明析构函数
private:
    string _name;        //声明表示兔子名字的成员变量
    char* _food;        //声明表示兔子食物的成员变量
};
Rabbit::Rabbit(string name, const char* pf)
{
    cout<<"调用构造函数"<<endl;
    _name=name;
    _food=new char[50];      //为_food指针申请空间
    memset(_food,0,50);      //初始化_food空间
    strcpy(_food,pf);       //将参数pf指向的数据复制到_food中
}
void Rabbit::eat()
{          //类外实现成员函数
    cout<<_name<<" is eating "<<_food<<endl;
}
Rabbit::~Rabbit()       //类外实现析构函数
{
    cout<<"调用析构函数,析构"<<_name<<endl;
    if(_food != NULL)
        delete []_food;
}
int main()
{
    Rabbit A("A","luobo");
    A.eat();
    Rabbit B("B","baicai");
    B.eat();
    return 0;
}
运行结果:

调用构造函数
A is eating luobo
调用构造函数
B is eating baicai
调用析构函数,析构B
调用析构函数,析构A

示例分析:
在创建对象的过程中,对象 A 与对象 B 除了对象本身所占用的内存空间,还各自拥有一块 new 运算符在堆上申请的空间,对象 A 与对象 B 占用的内存空间如图 1 所示。

图1 对象A与对象B占用的内存空间
图1 对象A与对象B占用的内存空间

程序运行结束后,编译器会调用析构函数释放对象资源,在释放时,先释放 _food 指向的内存空间,再释放对象所占用的内存空间。

由运行结果可知,程序成功调用了析构函数,并且析构的顺序是先析构对象 B,再析构对象 A。

优秀文章