【C++】构造与析构函数

目录:

一、 This指针 

(一)使用方法:

二、类的默认成员函数

三、构造函数 

(一)构造函数的特点

四、析构函数

(一)析构函数的特点


正文

一、 This指针

在c语言中我们调用函数初始化或进行一系列函数操作都要进行传值或传址调用,传址每次要取地址很是麻烦,于是C++祖师爷就像在C++上做一个优化,让编译器自己传地址而使用者只需要传参就行。This指针由此诞生了。

(一)使用方法:

(1)Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了⼀个隐含的this指针解决这⾥的问题。

用类创建对象后要进行初始化要写成以下的形式,个数必须与类中函数形参个数一模一样,不能少也不能多

(2)编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。

⽐如Date类的Init的真实原型为, void Init ( Date* const this,  int year, int month,  int day)而编译器规定this指针只能在形参第一个位置且不能显示写出来但可以显示调用。也就是当你调用类的成员变量时前面可写可不写this->,或是混着写都可以。有了this指针我们就不需要传d1、d2的地址,也就实现了谁调用就打印谁。

(3)类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this->_year = year;

(4)C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针。(如上图Init 在参数部分没写this指针却可以用this指针)

(5)有些人可能会问this指针为什么要加const修饰,在C语言部分有提过const要是加在*号右边表示该指针不能被改变,若是在*左边表示指针指向的内容不能改变。Date*表示该指针是Date这个类的指针。

两道习题讲解:

(1)

p是空指针,空指针编译器不一定会报编译错误它有可能检查不到错误,A错。

空指针访问类中的函数不会报错,因为没有解引用只是访问一下没有关系

(2)

此题和上题类似,唯一的区别在于Print函数内部,类函数存在this指针所以它通过空指针访问了_a这是不允许的操作。

二、类的默认成员函数

默认成员函数就是用户没有显示实现,编译器会自动生成的成员函数称为默认成员函数。

第一:我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求。

第二:编译器默认生成的函数不满足我们的需求,我们需要自己实现,那么如何自己实现?

三、构造函数

构造函数是特殊的成员函数,它不是开空间创建对象,而是对象实例化时自动初始化对象。

(一)构造函数的特点

(1)函数名与类名相同。

(2)⽆返回值。 (返回值啥都不需要给,也不需要写void,不要纠结,C++规定如此)

(3)对象实例化时系统会⾃动调⽤对应的构造函数。

(4)构造函数可以重载。

以上四点是教我们如何构造构造函数,下图为构造函数重载:

重载我在前一篇博客有讲,同名类函数只要参数类型和参数个数不同就构成重载。

(5)那么我们不写,编译器默认⽣成的构造,对内置类型成员变量的初始化没有要求,也就是说是否初始化是不确定的,看编译器。对于⾃定义类型成员变量,要求调⽤这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数,那么就会报错。(在没有构造函数情况下,要初始化这个成员变量,需要⽤初始化列表才能解决,初始化列表,我们下个章节再细细讲解)

内置类型:int 、float、 double 、指针.....

自定义类型:class、 struct、 union.....

比如下面这个日期类就得我们自己实现构造函数,因为日期类的成员变量全是内置类型,系统自动生成构造函数是随机值不符合预期。

那什么时候会自动生成有用的构造函数呢?如下图用两个栈实现一个队列,而两个栈已经开辟出来,它里面也有构造函数,那么我们自己要创建的队列MyQueue类就不用自己写构造,系统会自动调用自定义类型栈的构造函数。

什么叫默认构造函数?编译器自己生成的才是吗?

(6)如果类中没有显式定义构造函数,则C++编译器会⾃动⽣成⼀个⽆参的默认构造函数(其中一种),⼀旦⽤户显式定义编译器将不再⽣成。(默认构造函数后面第七点讲)

所以上面调的栈默认构造函数是不是编译器自己生成的呢?不是!栈里面的也是我们自己显示写的,如果把栈的默认构造屏蔽掉编译器调不了会报错。

只有一种情况自动生成的默认构造够我们用:这个类里面成员全是自定义类型,并且自定义类型已经有自己的默认构造函数

(7)⽆参构造函数、全缺省构造函数、我们不写构造时编译器默认⽣成的构造函数,都叫做默认构造函数。但是这三个函数有且只有⼀个存在,不能同时存在。⽆参构造函数和全缺省构造函数虽然构成函数重载,但是调⽤时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认⽣成那个叫默认构造,实际上⽆参构造函数、全缺省构造函数也是默认构造,总结⼀下就是不传实参就可以调⽤的构造就叫默认构造。

所以默认构造函数并不是只指编译器自己生成的,编译器自己生成就是上图那两个栈的例子,前提是你栈里面本身就有构造函数,而我们创建的队列就不用写构造编译器直接去调栈的称为编译器默认⽣成的构造函数,换句话说如果栈里面没有构造函数,编译器又自己生不成就会报错。

下图自定义类型栈的构造函数是个带参的,不满足默认构造函数语法,那MyQueue要求调用自定义类型的构造就不能调了,因为不存在会报错。

回到我们不写时,编译器默认生成的函数行为是什么?

行为就是:编译器对内置类型没有要求,自定义类型调用它自己的构造函数。

四、析构函数

析构函数不是完成对对象本身的销毁,是完成对象中资源的清理释放工作。C++规定对象在销毁时会自动调用析构函数,完成资源释放这样就不怕忘记清理了。

(一)析构函数的特点

(1)析构函数名是在类名前加上字符 ~。

(2)⽆参数⽆返回值。 (这⾥跟构造类似,也不需要加void)

(3)⼀个类只能有⼀个析构函数。若未显式定义(自己定义),系统会⾃动⽣成默认的析构函数(系统生成的大部分不满足需求,和自动生成构造函数定义类似)

(4)对象⽣命周期结束时,系统会⾃动调⽤析构函数。可理解为要释放一块空间先把空间内数据清理干净再释放。

(5)跟构造函数类似,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,自定类型成员一定会调用他自己的析构函数。

还是以上面两个栈实现一个队列的例子举例:自定义类型栈的内部自己实现了构造函数和析构函数,所以我们自己创建的队列MyQueue就可以编译器自动生成调用栈的析构,简直是人生赢家。

同样要是栈里面没有写析构函数那么编译器对自定义类型就无法自动生成析构,编译器报错!

所以所谓的自动生成是在自定义类型有的情况下,本质还是要自己写,大家理解一下。

(6)还需要注意的是我们显示写析构函数,对于⾃定义类型成员也会调⽤他的析构。也就是说⾃定义类型成员⽆论什么情况都会⾃动调⽤析构函数。

(7)如果类中没有申请资源时,析构函数可以不写,直接使⽤编译器⽣成的默认析构函数,如Date;如果默认⽣成的析构就可以⽤,也就不需要显示写析构,如MyQueue;但是有资源申请时,⼀定要⾃⼰写析构,否则会造成资源泄漏,如Stack栈。

对日期类型不用写析构是因为它里面全是内置类型也没指向什么资源根本不需要释放,年月日属于对象的成员,函数结束栈帧销毁他就销毁了。

回到我们不写时,编译器默认生成的函数行为是什么?

行为就是:编译器对内置类型不做处理,自定义类型调用它自己的析构函数。

易忽略点:

(1)造顺序是按照语句的顺序进行构造,析构是按照构造的相反顺序进行析构

(2)构造函数可以是私有的,只是这样之后就不能直接实例化对象

(3)类的析构函数调用一般按照构造函数调用的相反顺序进行调用,但是要注意static对象的存在, 因为static改变了对象的生存作用域,需要等待程序结束时才会析构释放对象


本节完

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

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

相关文章

2021TCSVT,VDM-DA:面向无源数据域自适应的虚拟域建模

原文标题:VDM-DA: Virtual Domain Modeling for Source Data-free Domain Adaptation 中文标题:VDM-DA:面向无源数据域自适应的虚拟域建模 1、Abstract 领域适应旨在利用标签丰富的领域(源领域)来帮助标签稀缺领域&…

MySQL数据库1——数据库概论

一.数据库概论 1.数据库 数据库(DataBase,DB):是长期存储在计算机内、有组织的、统一管理的相关数据的集合。简单来说,它就是一个存储各种数据的仓库,且存储过程不是随便而是有组织的。 数据库管理系统&am…

英伟达Tensor Core技术架构原理分析

英伟达Tensor Core架构技术原理 英伟达的Tensor Core架构是一种专为加速人工智能、深度学习、高性能计算(HPC)等领域中的矩阵运算和张量运算而设计的硬件单元。自首次在Volta架构中引入以来,Tensor Cores已成为NVIDIA高端GPU的核心特性,并在后续的Turing…

Linux基础5-进程控制1(fork创建子进程,写时拷贝,进程退出)

上篇文章:Linux基础4-进程5(程序地址空间详解)-CSDN博客 本篇重点:fork,写实拷贝,进程退出 目录 一. fork创建子进程 1.1 fork用法 1.2 fork返回值有两个的理解 二. 进程退出码 2.1 进程退出码 2.2 进…

用python中的tkinter包实现进度条

python中的tkinter包是一种常见的设计程序的GUI界面用的包。本文主要介绍这里面的一个组件:进度条(Progressbar)。Tkinter Progressbar里面对进度条组件已经做了一定的介绍,但比较抽象。本文以另一种方式介绍这个组件及其常用用法…

20.使用标准差剔除异常值

标准差剔除异常值 1. 方法2. 示例代码2.1 数据读取与清洗2.2 分段读取数据并绘图2.3 解释2.4 outliers2.5 结果展示 我有个记录数据采集后格式是step_rewards.txt 的文档,里面只有一列数据,10*10000行数据,没有表头,分别代表奖励数…

中科蓝讯修改蓝牙名字:【图文讲解】

本文以市面上一款公板公模的畅销产品为例。K12蓝牙音响。 音响用的芯片是:AB5768E MIC用的芯片是:AB5769A 硬件框架图如下: 芯片修改名字,通过下载工具中的配置进行修改。选择蓝牙配置,然后会出现蓝牙名字&#xff…

旅行包发霉怎么处理 除霉及防霉解决方法

近些年听到很多箱包工厂的心声,为什么箱包旅行包每年都会出现长霉请况呢?长霉了,也就是长毛了,长出那些病菌、真菌、细菌等微生物。经ihaoer防霉人士介绍旅行包长霉处理方法如下: 旅行包长霉的因素 一、旅行包储存在阴…

14、交互补充

1、元素的三大系列 1.1、offset系列 1.1.1、offset初相识 使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等 获得元素距离带有定位祖先元素的位置获得元素自身的大小(宽度高度)注意:返回的数值都不…

【IEEE出版、八大高校联合举办、稳定EI检索】第四届人工智能与智能制造国际研讨会(AIIM 2024,12月20-22日)

第四届人工智能与智能制造国际研讨会(AIIM 2024) The 4th International Symposium on Artificial Intelligence and Intelligent Manufacturing 2024年12月20-22日 中国成都 重要信息 大会官网:www.isaiim.com 大会时间:202…

朴素贝叶斯算法探讨与实践

引言 和撰写博文[1]的缘由一样,本文是想要在所创设的专栏[2]里把所谓的十大机器学习算法[3]全部过一遍。 朴素贝叶斯算法是传统机器学习里的一种可以被用来进行分类的算法,本文将对其原理进行说明,并基于原理给出一个基于该算法的分类实践。…

《数据在内存中的存储》

内存函数 1. 整数在内存中的存储 (1)旧识回顾: 之前在学到操作符的时候,我们就学过了下面的内容: 整数的二进制的表示方式有三种,原码、反码、补码 有符号的整数,三种表示方式均有符号位和数…

【路径规划】粒子群算法、遗传算法、差分进化算法、灰狼优化算法、麻雀优化算法(PSO、GA、DE、GWO、SSA)路径规划

摘要 本文探讨了多种智能优化算法在路径规划中的应用,包括粒子群算法(PSO)、遗传算法(GA)、差分进化算法(DE)、灰狼优化算法(GWO)和麻雀优化算法(SSA&#x…

CSS基础知识05(弹性盒子、布局详解,动画,3D转换,calc)

目录 0、弹性盒子、布局 0.1.弹性盒子的基本概念 0.2.弹性盒子的主轴和交叉轴 0.3.弹性盒子的属性 flex-direction row row-reverse column column-reverse flex-wrap nowrap wrap wrap-reverse flex-dirction和flex-wrap的组合简写模式 justify-content flex-s…

如何搭建一台邮箱服务器,配置满分邮箱

如何搭建一台邮箱服务器,配置满分邮箱 搭建一台个人邮箱服务器听上去非常有技术含量,但只要准备工作充分,并且选择合适的软件,配置满分的邮箱,其实并没有想象中那么困难。在这篇文章中,我们将介绍搭建邮箱服务器的 必备…

DevOps工程技术价值流:打造卓越项目协作的优化宝典

一、引言 解锁项目协作的无限潜力,覆盖全链路实现流畅高效。 在当今瞬息万变的商业环境中,项目协作的效率和效果直接关系到企业的竞争力和市场响应速度。DevOps工程技术价值流中的项目协作优化,不仅是技术层面的革新,更是团队协…

【JAVA毕业设计】基于Vue和SpringBoot的冬奥会科普平台

本文项目编号 T 610 ,文末自助获取源码 \color{red}{T610,文末自助获取源码} T610,文末自助获取源码 目录 一、系统介绍二、数据库设计三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状 六、核心代码6.1 查询项目类型6.…

基于的图的异常检测算法OddBall

OddBall异常检测算法出自2010年的论文《OddBall: Spotting Anomalies in Weighted Graphs》,它是一个在加权图(weighted graph)上检测异常点的算法,基本思路为计算每一个点的一度邻域特征,然后在整个图上用这些特征拟合出一个函数&#xff0c…

网络工程师教程第6版(2024年最新版)

网络工程师教程(第6版)由清华大学出版社出版,由工业和信息化部教育与考试中心组编,张永刚、王涛、高振江任主编,具体介绍如下。 相关信息: 出版社: 清华大学出版社 ISBN:9787302669197 内容简介: 本书是工业和信息化部教育与考试中心组织编写的考试用书。本书 根据…

算法复杂度——大O表示法

参考视频:常见的大O表示法有哪些?时间复杂度是什么?_哔哩哔哩_bilibili