C++对象模型(13)-- 构造函数语义学:析构函数

news2025/7/19 14:28:19

1、默认析构函数生成规则

跟构造函数一样,编译器不一定会为类生成默认析构函数。生成默认析构函数的规则有下面2条:

(1)包含一个类类型的成员变量,且成员变量所属的类有默认析构函数。

(2)其父类有默认析构函数。

我们可以通过VS2019的反汇编代码来验证这2条规则:

class Base {
public:
    ~Base(){}
};

class Derive: public Base{
};

int main()
{
    Derive derive;
    return 0;
}

反汇编窗口中的代码如下:

2、继承中的析构函数

继承中的析构顺序跟构造顺序相反:由外而内,即先析构子类对象,再析构父类对象,整个过程就跟剥洋葱一样。

我们可以用这个例子验证析构顺序:

class Base {
public:
    ~Base() {
        std::cout << "~Base" << std::endl;
    }
};

class Derive : public Base {
public:
    ~Derive(){
        std::cout << "~Derive" << std::endl;
    }
};

int main()
{
    Derive derive;
    return 0;
}

程序运行结束后,打印:

~Derive

~Base

3、虚析构函数

基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果要用基类对继承成员进行操作,则要把基类的这个成员函数定义为虚函数,析构函数同样需要如此。

用基类指针来删除派生类的对象,而这个基类的析构函数不是虚函数,则对象的派生部分不会被销毁,这会导致内存泄露。

class Base {
public:
    ~Base() { 
        std::cout << " ~Base" << std::endl;
    }
};

class Derive : public Base {
public:
    ~Derive(){
        std::cout << " ~Derive" << std::endl;
    }
};

int main()
{
    Base *pb = new Derive();
    delete pb;

    return 0;
}

程序运行后输出:~Base

没有调用Derive类的析构函数。

要解决这个内存泄漏问题,只需要把基类的析构函数改成虚析构函数就可以了:

virtual ~Base(){};

4、多重继承时的析构函数

修改上面的代码,增加一个类Base2:

class Base2 {};

并让Derive继承这个类Base2:

class Derive : public Base, public Base2 {}

现在这个类Derive的对象布局是这样的:

我们在main()函数里添加如下代码:

int main()
{
    Base2 *pb2 = new Derive();
    delete pb2;

    return 0;
}

执行代码后发现报错。是什么原因呢?

因为现在pb2指向的是类Base2对象,执行delete时就必须把整个类Derive对象给删除,现在只删除了部分对象,肯定是不行的。那么怎么delete整个类Derive对象呢?

把类Base2的析构函数写成虚析构函数:

virtual ~Base2(){};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1102750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习笔记 - 3D 对象跟踪极简概述

一、简述 大多数对象跟踪应用程序都是 2D 的。但现实世界是 3D 的,无论您是跟踪汽车、人、直升机、导弹,还是进行增强现实,您都需要使用 3D。在 CVPR 2022(计算机视觉和模式识别)会议上,已经出现了大量3D目标检测论文。 二、什么是 3D 对象跟踪? 对象跟踪是指随着时间的…

柔性数组的使用及注意事项

1.柔性数组在结构体当中,并且在结构体的最后面. 2.结构体中除了柔型数组外至少还要有一个其他成员. 3.sizeof()返回结构体的大小不包含柔性数组的大小. 4.malloc 例:struct sdshdr16 *p malloc(sizeof (struct sdshdr16) 32); // 32 为柔性数组的大小 5.free 例: fre…

weblogic任意文件上传漏洞操作(CVE-2018-2894)

运行weblogic&#xff0c;直接找到目录运行&#xff0c;或者cmd命令打开运行 启动之后如下&#xff1a;http://192.168.246.11:7001/console/login/LoginForm.jsp 打开网页http://192.168.0.127:7001/ws_utc/config.do 修改默认路径C:\Oracle\Middleware\Oracle_Home\user_pro…

Express入门指南(详细)

文章目录 &#x1f7e2; Express⭐️ 1.初始Express✨安装✨使用Express 搭建一台服务器 ⭐️2.Express-基本路由✨1.使用字符串模式的路由路径示例&#xff1a;✨2.使用正则表达式的路由路径示例&#xff1a;✨3.中间件浅试(demo) ⭐️3.Express-中间件✨1.应用级中间件✨2.路…

图详解第四篇:单源最短路径--Dijkstra算法

文章目录 1. 最短路径问题2. 单源最短路径--Dijkstra算法算法思想图解如何存储路径及其权值代码实现调式观察打印最短路径Dijkstra算法的缺陷 3. 源码 1. 最短路径问题 最短路径问题&#xff1a; 从带权有向图&#xff08;求最短路径通常是有向图&#xff09;G中的某一顶点出发…

git学习——第4节 时光机穿梭

我们已经成功地添加并提交了一个readme.txt文件&#xff0c;现在&#xff0c;是时候继续工作了&#xff0c;于是&#xff0c;我们继续修改readme.txt文件&#xff0c;改成如下内容&#xff1a; Git is a distributed version control system. Git is free software. 现在&…

甘特图组件DHTMLX Gantt示例 - 如何有效管理团队工作时间?(二)

如果没有有效的时间管理工具&#xff0c;如工作时间日历&#xff0c;很难想象一个项目如何成功运转。这就是为什么我们的开发团队非常重视项目管理&#xff0c;并提供了多种选择来安排DHTMLX Gantt的工作时间。使用DHTMLX Gantt这个JavaScript库&#xff0c;您可以创建一个强大…

python:代码加密

一、将py文件打包成pyc文件 import py_compilepy_compile.compile(rsshare.py)二、机器码加密和解密 示例&#xff1a; 原始机器码输入&#xff1a;‘BRRWQZ8’ 加密机器码输出&#xff1a;‘QlJDDFFSMw’ import base64 # 要加密的字符串 original_string BRRDDL3 # 编码&…

基于R语言实现中介效应检验以及sobel检验代码

数据格式 随机数据&#xff0c;不一定好 y是因变量&#xff0c;x是自变量&#xff0c;m是中介变量 基本原理 M ~ X Y ~ X Y ~ X M 直接上代码 library(mediation) library(bda)# 加载readxl包 library(readxl) # 读取Excel表格# 读取数据 我是从剪切板读取的 data read…

标签页的使用

目录 1、引用TabSheet.h和TabSheet.cpp文件&#xff1a; 2、主窗口添加标签页&#xff1a; &#xff08;1&#xff09;、标签页的创建和属性更改 &#xff08;2&#xff09;、添加俩个标签页的类 &#xff08;3&#xff09;、主窗口添加成员变量 &#xff08;4&#xff09…

[补题记录] Atcoder Beginner Contest 324(E、F)

URL&#xff1a;https://atcoder.jp/contests/abc324 目录 E Problem/题意 Thought/思路 Code/代码 F Problem/题意 Thought/思路 Code/代码 E Problem/题意 给出 N 个字符串和 1 个 T 字符串&#xff0c;都由小写字母组成。 现在从 N 个字符串中任取 2 个拼接&…

电子邮件地址注册过程详解

许多人可能对如何注册电子邮件地址感到困惑&#xff0c;本文将详细解析电子邮件地址的注册过程&#xff1a;确定邮箱厂商、创建邮箱账户、设置电子邮件地址。 1、确定要注册的邮箱厂商 首先我们需要确定要注册哪种类型的电子邮件服务。目前市场上有许多不同的电子邮件服务提供商…

实现日期间的运算——C++

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…

Java内存模型-Java Memory Model(JMM)-可见性、原子性、有序性

5. Java内存模型之JMM 5.1 先从大场面试开始 你知道什么是Java内存模型JMM吗&#xff1f; JMM和volatile他们两个之间的关系&#xff1f; JMM没有那些特征或者它的三大特征是什么&#xff1f; 为什么要有JMM&#xff0c;它为什么出现&#xff1f;作用和功能是什么&#xf…

C++数据结构X篇_15_求二叉树叶子数与高度(递归方法)

本篇参考求二叉树叶子数与高度&#xff08;C&#xff09;进行整理。 文章目录 1. 二叉树中叶子数与高度2. 求二叉树叶子数与高度的实现代码 1. 二叉树中叶子数与高度 我们首先来看一看二叉树中叶子数与高度的定义&#xff1a; 叶子数&#xff1a;对于一个二叉树的节点&#x…

【微信小程序】6天精准入门(第3天:小程序flex布局、轮播图组件及mock运用以及综合案例)附源码

一、flex布局 布局的传统解决方案&#xff0c;基于[盒状模型]&#xff0c;依赖display属性 position属性 float属性 1、什么是flex布局&#xff1f; Flex是Flexible Box的缩写&#xff0c;意为”弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性。任何一个容器都可以…

基于五折交叉验证的支持向量机SVR回归预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)

一&#xff1a;排序的概念及引入 1.1 排序的概念 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在…

[Python中常用的回归模型算法大全2:从线性回归到XGBoost]

文章目录 概要多输出K近邻回归集成算法回归梯度提升决策树回归随机森林回归 概要 回归分析在数据科学领域扮演着关键角色&#xff0c;用于预测数值型目标变量。本文深入探讨了几种常用的回归模型&#xff0c;包括多输出K近邻回归&#xff0c;决策树回归&#xff0c;集成算法回…