文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++析构函数内部工作机制详解

2023-02-27 11:33

关注

我们主要从三个方面来学习析构函数的工作原理:

1、析构函数的内部工作机制

众所周知,在对象的生命周期结束时会自动调用析构函数用于清理对象所申请的资源,那么它是如何清理的呢?

析构函数会调用delete函数释放对象中new出来的空间,即析构函数通过delete函数来清理对象所申请的资源,当然如果对象没有申请资源,那么就无需调用delete函数

由于是new出来的对象是在堆上分配空间的,即使离开了作用域,其依然存在,我们必须在析构函数中主动delete来释放new出来的在堆上的空间,否则对象消亡后,离开了作用域后,指向该空间的数据成员(指针)就会消失,我们失去了对这片空间的控制权,别人也无法使用这片空间,这就会造成内存泄漏。

如果对象是new出来的,那么它就是一个堆对象,不会被 操作系统自动回收,需要我们手动调用delete函数释放该堆对象,在delete函数中会先调用析构函数释放该对象所申请的资源,那么析构函数如何释放对象所申请的资源呢,就是前面所说的,析构函数又会调用delete函数来释放对象所申请的资源,当然如果对象没有申请资源,那么就无需调用delete函数。

#include <iostream>
using namespace std;
class Person {
public:
    Person() {
        cout <<  "调用了Person的构造函数" << endl;
    }
    ~Person() {
        cout << "调用了Person的析构函数" << endl;
    }
private:
    int name;
};
int main() {
    Person* person = new  Person();
    delete person;
    return 0;
}

2、默认析构函数的内部工作机制

我们清楚了析构函数的内部工作机制后,继续思考一个问题,默认析构函数它的内部是怎么工作的呢?

我们先来看看下面这段代码

class Time
{
public:
	~Time()
	{
		cout << "~Time()" << endl;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}

程序运行结束后输出:~Time(),在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?

这就涉及到默认析构函数的内部工作机制了。

默认析构函数,对于基本类型成员不做处理,对于自定义类型成员会去调用它的析构函数。

总结: 默认构造函数对基本类型不做处理,对自定义类型会调用它的默认构造函数,默认拷贝构造函数对基本类型是按照字节方式直接拷贝的,对自定义类型是调用其拷贝构造函数完成拷贝的,默认析构函数对基本类型不做处理,对自定义类型会调用它的析构函数。默认赋值运算符对基本类型成员变量以值的方式逐字节拷贝。而对自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

默认构造函数只有一个,析构函数只有一个,拷贝构造函数只有一个,赋值运算符重载只有一个

如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,什么事都不会干,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏

3、析构函数的调用

析构函数在对象消亡时被调用,以清理对象所申请的资源,那具体它在何时被调用呢?

析构函数主要在以下4种情况下会被调用:

对象生命周期结束,此时会自动调用析构函数。

#include<iostream>
using namespace std;
class Person {
public:
    Person() {
        cout << "调用了Person的构造函数" << endl;
    }
    ~Person() {
        cout << "调用了Person的析构函数" << endl;
    }
private:
    int name;
};
int main() {
    Person person;
    return 0;
}

运行结果如下图所示:

该运行结果说明,在对象的生命周期结束后,会自动调用对象的析构函数。

成员关系:对象car是对象person的成员,person的析构函数被调用时,对象car的析构函数也被调用。

#include <iostream>
using namespace std;
class Car {
public:
    Car() {
        cout << "调用了Car的构造函数" << endl;
    }
    ~Car() {
        cout << "调用了Car的析构函数" << endl;
    }
private:
    int name;
};
class Person {
public:
    Person() {
        cout << "调用了Person的构造函数" << endl;
    }
    ~Person() {
        cout << "调用了Person的析构函数" << endl;
    }
private:
    int name;
    Car car;
};
int main() {
    Person person;
    return 0;
}

先调用的是包含类的析构函数,然后调用的是成员对象的析构函数

继承关系:当Person是Student的父类,调用Student的析构函数,会调用Person的析构函数。

#include <iostream>
using namespace std;
class Person {
public:
    Person() {
        cout << "调用了Person的构造函数" << endl;
    }
    ~Person() {
        cout << "调用了Person的析构函数" << endl;
    }
private:
    int name;
};
class Student :public Person {
public:
    Student() {
        cout << "调用了Student的构造函数" << endl;
    }
    ~Student() {
        cout << "调用了Student的析构函数" << endl;
    }
private:
    int name;
    string no;
};
int main() {
    Student student;
    return 0;
}

先调用的是派生类的析构函数释放派生类的资源,然后调用的才是父类的析构函数释放父类成员所指向的资源

值得注意的是,如果派生类对象是new出来的对象,基类指针指向一个new生成的派生对象,通过delete销毁基类指针指向的派生类对象时,有以下两种情况:

1、 如果基类析构函数不是虚析构函数,则只会调用基类的析构函数,派生类的析构函数不被调用,此时派生类中申请的资源不被回收。

2、 如果基类析构函数为虚析构函数,则释放基类指针指向的对象时会调用基类及派生类析构函数,派生类对象中的所有资源被回收。

到此这篇关于C++析构函数内部工作机制详解的文章就介绍到这了,更多相关C++析构函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯