类的6个默认成员函数(上)

news2024/12/22 18:56:52
                        <center>Efforts of today and tomorrow.<center>

在这里插入图片描述
 今天的努力,明天的实力。开启本文!
引入:
 如果一个类中森么都没有,那么这个类就是空类,然而空类中真的是什么都没有吗?
其实不然,介绍一下类的6个默认成员函数。
 为什么叫默认成员函数呢?正如上边所说,默认成员函数数用户没有显式显示,编译器会自动生成的成员函数。
总览如下,接下来进行逐个讲解,如果只是某一个迷惑,可以通过目录直达痛点。
在这里插入图片描述

文章目录

      • 构造函数
      • 析构函数
      • 拷贝构造函数

构造函数

前边我们向一个类中的成员变量赋值,通常是写一个Init函数,就像这样
在这里插入图片描述
 但每次创建对象时都要调用该方法设置信息,就显得有点麻烦,能否在创建对象时,就将信息设置进去呢?
这就是构造函数函数存在的原因。
 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象(int类型变量,类类型对象,起始觉得拗口的话,现在懂了吧)时由编译器自动调用,保证每个成员变量都有一个合适的初始值,在整个生命周期只调用一次。
构造函数的特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
特征如下:

  • 函数名与类名相同。
  • 无返回值。
  • 对象实例化时编译器自动调用对应的构造函数。
  • 构造函数可以重载。

默认构造函数有三种,分别是如果我们没有写,编译器默认生成的无参构造函数,自己写的无参构造函数,全缺省的构造函数(要记住)。
在这里插入图片描述
 编译器自动生成和上图中第一个构造函数相同,可以看出,上边代码编译器自己所构造出的构造函数好像是没有什么作用的,上边还写了一个全缺省的构造函数,因为有两个构造函数,运行后报错就是包含多个默认构造函数。
要注意一旦我们自己写构造函数,那么编译器就不再生成默认的构造函数
在这里插入图片描述

 因为我们一旦显式定义任何构造函数,但该构造函数不符合默认构造函数的条件,编译器也不会自动生成默认构造函数,所以才会这么报错。
 上边所说,默认构造函数在我们实例化对象时会自动调用,我们自己写的默认构造函数可以随意修改,例如
在这里插入图片描述
我们调用了吗?没有啊,但是他为什么自己运行了?这就是编译器自行调用。
但是编译器默认生成的构造函数内部空空如也,那他有什么用呢?
看下图
在这里插入图片描述
 我们知道,C++类中不仅可以有内置类型(基本类型),当然也可以有自定义类型,内置类型就是语言自带的数据类型,比如int,char,double等,自定义类型就是我们自己使用class,struct,union等自己定义的类型。
如果我们实例化对象的类中有自定义类型,编译器默认生成的构造函数会自行调用自定义成员的默认构造函数,就比如我们用两个栈实现队列时,创造的栈结构体类型的变量在队列的构造函数中可以不用考虑,他会自动去调用栈对应的构造函数(这样就不需要我们操心我们定义的类中如果有其他类的成员,就会自己调用自己的构造函数,不需要我们这个类操心了)。
补充说明
和C语言不同的是,我们实例化内置类型不仅可以用全缺省构造函数,也可以给类中内置类型在声明中就给缺省值。
下图为C语言,明显不可以给缺省值。
在这里插入图片描述
C++全缺省构造函数
在这里插入图片描述
声明时给默认值
在这里插入图片描述
构造函数总结
 如果我们没有给默认值,也没有写全缺省构造函数,那么内置类型就都不会处理,自定义类型会调用他自己的构造函数,至于其中的细节看了上边的描述我想你已经拿捏了。

析构函数

 通过上边的例子,我们已经知道了一个类是怎么来的了。那么我们如何来销毁创造出来的对象呢?
介绍:
与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象的销毁工作时由编译器来完成的,对象在销毁时自动调用析构函数,完成对象中资源的清理工作。
特性:

  • 析构函数名是在类名前加上字符 ~
  • 无参数无返回值类型
  • 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载(没有参数,也没有重载条件)
  • 对象生命周期结束时,C++编译系统系统自动调用析构函数。

上边我们说了类中局部对象的销毁工作是有编译器来完成的,那么析构函数的作用是什么呢?
 要注意的是,堆上的空间是有我们自行控制的,当我们malloc或者new一段新空间时,需要分别调用销毁free(或delete)掉他们,C++利用析构函数让我们在销毁空间时更加方便(自动调用,内部细节全部封装好了,不需要我们关心)。当对象要释放时自行调用,像构造函数一样,如果一个类中有自定义类型,也会自动调用该自定义类型的析构函数。
百闻不如一见,析构函数的作用如下。
在这里插入图片描述
如上图所示。析构函数就是用来回收内存资源的。
我带大家来调试看一看他们调用的时机。
在这里插入图片描述

 可以看出,在实例化一个对象时,就回去调用它的构造函数,该对象的生命周期是在TestStack中,所以在这个函数结束时,还回去调用该类的析构函数,然后释放该对象所占据的空间。
析构函数总结:
 类中成员变量如果是内置类型成员,最后是由系统回收的,而该类中的自定义成员会调用他自己的析构函数。析构函数主要是用来free或delete申请的内存资源。如果类中没有申请资源,那就可以直接使用编译器默认的析构函数,如果有资源申请的话,一定要自己写析构函数,不然就会造成资源泄漏。
调用顺序
如果一个类中包含着自定义变量,在我们用该类实例化对象时,他们的构造函数和析构函数的调用顺序是怎么样的呢?

看该例

class Stack
{
public:
	Stack()
	{
		arr = new int[_capacity] ;
		_size = 0;
		cout << "Stack的构造函数" << endl;
	}
	~Stack()
	{
		delete arr;
		cout << "Stack的析构函数" << endl;
	}
	int* arr;
	int _capacity=20;
	int _size;
};
class Quene
{
public:
	Quene()
	{
		cout << "Quene的构造函数" << endl;
	}
	~Quene()
	{
		cout << "Quene的析构函数" << endl;
	}
	Stack _s1;
};
int main()
{
	Quene q1;
	return 0;
}

在这里插入图片描述
运行后发现,先调用自定义成员的构造函数,然后再调用自己的构造函数。
 可以这样想,如果我们需要一个电脑,他的配件都还没配置好,怎么配置好一台电脑呢?所以我们要先把配件都准备齐全,然后构造电脑。同样的道理,调用析构函数时先把电脑砸了,然后再把配件砸掉,这样理解就会很容易记住。

拷贝构造函数

概念
 拷贝构造函数:该函数只有一个形参,该形参类型是对本类类型对象的引用(一般用const修饰防止被误改),用已存的类类型对象创建新对象时,由编译器自动调用。
特征

  • 拷贝构造函数是构造函数的一个重载形式
  • 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。

用一下认识认识

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

 在主函数中,我们通过已经构造好的类类型对象实例化出d1对象。看上边拷贝构造函数的用法,此时this指针就指向d2,所以拷贝构造函数是将传过去的同类型对象赋值一份,所以它叫做拷贝构造函数。
现在解决第二个问题,为什么形参只能是同类类型对象的引用?
在这里插入图片描述
如果直接传时就会报出不能是Date类型的参数,因为会引发无穷递归。
在这里插入图片描述
 在以值传参时,因为要产生一个新的形参传递过去,要想产生和该对象一样的形参,就要调用该对象(d1)的拷贝构造函数生成形参d,要想将形参d以值传参返回,那就要调用d的拷贝构造函数生成一个新的形参e,要想将e以值传参的形式,又要调用形参e的拷贝构造函数产生一个新的对象f,一直循环,所以会引发无穷递归。(足够清晰明了不?)
 所以在写拷贝构造时一定要记得形参为实参的引用,怕实参被修改可以加一个const修饰。

 如果拷贝构造函数没有显式调用,那么编译器就会默认生成一个拷贝构造函数,默认生成的拷贝构造函数拷贝出的对象是按照传参对象的字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝,这种拷贝方式可以完成内置类型的拷贝工作。但是对于需要开空间的成员,例如一个指针指向开一定空间的首元素地址,则只会将该指针的值赋给拷贝后的成员变量。
正如前边所写的栈,会使用new在堆上开辟空间。
在这里插入图片描述
这是因为在使用编译器默认提供的拷贝构造函数时进行的是浅拷贝。
在这里插入图片描述
 还记得吗,我们实例化一个对象后,当该对象使用结束会地洞调用该对象的析构函数,当析构完s1后,再析构s2,此时s2的arr指向的内容已经在析构s1时清空了,再释放该位置时就会出现一块空间多次释放的问题,所以才会造成程序崩溃。
 所以要注意:如果类中涉及资源申请,一定要显式的写拷贝函数,如果没有涉及资源调用的话,拷贝构造函数写不写都可以,编译器会给你安排。
在这里插入图片描述
上边的例子的拷贝构造函数,呐。
拷贝构造函数的使用场景

  • 使用已有对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

 使用拷贝构造传参或返回时,需要调用拷贝构造函数生成一个一模一样的形参(具有常性,用完就無),如果这个对象不大还比较好,如果该函数很大的话还好,如果该对象包含很大的结构,在拷贝构造时需要很大的时间开销,所以我们在传参时可以选择引用传参,这样就可以节省很大的时间开销。当然,如果怕在函数中被修改可以用const修饰即可。

 本文到这里就结束啦,下一篇文章会讲到赋值运算符重载,普通或const修饰对象取地址操作。有用的话留一个赞再走叭,如果你的慧眼金睛发现了问题,一定要说哦,我会虚心改正的。

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

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

相关文章

第五节 操作符

第五节 操作符 目录 一&#xff0e; 操作符分类二&#xff0e; 算术操作符三&#xff0e; 移位操作符1. 二进制位2. 左移操作符3. 右移操作符 四&#xff0e; 位操作符1. 按位与2. 按位或3. 按位异或 五&#xff0e; 赋值操作符六&#xff0e; 单目操作符1. 概述2. sizeof是操作…

【Spring教程31】SSM框架整合实战:从零开始学习SSM整合配置,如何编写Mybatis SpringMVC JDBC Spring配置类

目录 1 流程分析2 整合配置2.1 步骤1&#xff1a;创建Maven的web项目2.2 步骤2:添加依赖2.3 步骤3:创建项目包结构2.4 步骤4:创建SpringConfig配置类2.5 步骤5:创建JdbcConfig配置类2.6 步骤6:创建MybatisConfig配置类2.7 步骤7:创建jdbc.properties2.8 步骤8:创建SpringMVC配置…

k8s安装配置dashboard

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

kali-捆绑应用程序

文章目录 一、安装开发环境二、开始捆绑三、开始监听 操作环境 kali windows 一、安装开发环境 ┌──(kali㉿kali)-[~] └─$ sudo -i [sudo] kali 的密码&#xff1a;┌──(root㉿kali)-[~] └─# whoami root┌──(root㉿kali)-[~] └─# apt update …

(七)STM32 NVIC 中断、优先级管理及 AFIO 时钟的开启

目录 1. 中断相关知识简介 1.1 什么是中断 1.2 什么是内中断、外中断 1.3 什么是可屏蔽中断、不可屏蔽中断 2. CM3 内核中断介绍 2.1 F103系统异常清单 2.2 F103 外部中断清单 3. NVIC 简介 3.1 NVIC 寄存器简介 3.2 NVIC 相关寄存器的介绍 4. 中断优先级 4.1 优先…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

洛谷 P8794 [蓝桥杯 2022 国 A] 环境治理

文章目录 [蓝桥杯 2022 国 A] 环境治理题目链接题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路解析CODE给点思考 [蓝桥杯 2022 国 A] 环境治理 题目链接 https://www.luogu.com.cn/problem/P8794 题目描述 LQ 国拥有 n n n 个城市&#xff0c;从 0 0 …

【无标题】CTF之SQLMAP

拿这一题来说 抓个包 复制报文 启动我们的sqlmap kali里边 sqlmap -r 文件路径 --dump --dbs 数据库 --tables 表

【老牌期刊】IF:6+,2天预审,3-5个月录用!

期刊简介 1区计算机智能类SCI 【期刊概况】IF&#xff1a;6.0-7.0&#xff0c;JCR1区&#xff0c;中科院2区&#xff1b; 【终审周期】走期刊部系统&#xff0c;3个月左右录用&#xff1b; 【检索情况】SCI检索&#xff1b; 【WOS收录年份】2018年&#xff1b; 【自引率】…

远程桌面连接软件除了Todesk还能用什么?

自从昨天Todesk开始报错&#xff0c;开始寻找好用的远程桌面连接软件&#xff0c;目前尝试了解到的免费的有RayLink和Teamviewer&#xff1a; TeamViewer&#xff1a;就个人来讲&#xff0c;感觉用户体验不是很友好 &#xff1a; 有什么好用的免费的远程桌面连接软件&#xff0…

html中RGB和RGBA颜色表示法

文章目录 RGB什么是RGBRGB颜色模式的取值范围RGB常用颜色对照表 RGBA什么是RGBARGBA颜色模式的取值范围 总结 RGB 什么是RGB RGB是一种颜色空间&#xff0c;其中R代表红色&#xff08;Red&#xff09;、G代表绿色&#xff08;Green&#xff09;、B代表蓝色&#xff08;Blue&a…

外汇天眼:芝加哥商品交易所(CME)对鹰七公司规定进行罚款

国际衍生品市场CME集团发布了一则关于Eagle Seven LLC的纪律行动通知。根据一项和解提议&#xff0c;其中Eagle Seven LLC既未承认也未否认任何违规规定或事实陈述&#xff0c;纽约商业交易所&#xff08;NYMEX&#xff09;业务行为委员会的一个小组认定&#xff0c;在2022年2月…

非专业的建模人员如何给模型设置材质纹理贴图?

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 1、材质和纹理的区别于关联 材质&#xff08;Material&#xff09;是…

【HarmonyOS开发】ArkTs实现侧栏联动

侧栏联动功能模块&#xff1a; 1、切换左侧导航&#xff0c;右侧滚动到对应的内容。 2、滚动右侧的内容&#xff0c;左侧会切换对应的导航。 1、涉及知识点 List&#xff08;列表组件&#xff09;、ListItemGroup&#xff08;列表item分组&#xff09; 2、效果预览 3…

AI数字人短视频矩阵怎么做?

AI数字人是什么&#xff1a;你可以通过我们的系统克隆出多个AI形象&#xff0c;每个数字人都有独特的个性和风格。无论是批量制作短视频&#xff0c;还是直播7*24小时都可以。数字人就是用AI技术根据你的真人形象克隆出一个数字人&#xff0c;跟真人的相似度可以达到100&#x…

【FAQ】运动健康服务云侧数据常见问题及解答

目录 Q1&#xff1a;v2接口相比于v1接口传参及返回的数据格式有变化吗&#xff1f;是否可以直接将v1接口改成v2接口&#xff1f; Q2&#xff1a;如何获取采集健康数据的穿戴设备信息&#xff1f; Q3&#xff1a;如何处理非华为手机产生的步数调用采样明细接口查询不到数据&a…

STM32-I2C通讯-AHT20温湿度检测

非常感谢&#xff0c;提供的视频学习 https://www.bilibili.com/video/BV1QN411D7ak/?spm_id_from333.788&vd_source8ca4826038edd44bb618801808a5e076 该文章注意&#xff1a;串口显示中文会乱码&#xff0c;必须选用支持ASCII的串口助手&#xff0c;才能正常显示中文。…

软考真的只准计算机专业报考吗?其实你也可以!

因为软考的全称为计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;很多人误以为软考只允许计算机专业的人报考&#xff0c;实际上并非如此~ 首先&#xff0c;让我们一起来看一下软考的报考条件 软考报考条件 软考的报考条件相对宽松&#xff0c;有…

自动化测试知识总结(含资料)

一、自动化测试 自动化测试的定义&#xff1a;使用一种自动化测试工具来验证各种软件测试的需求&#xff0c;它包括测试活动的管理与实施、测试脚本的开发与执行。 自动化测试只是测试工作的一部分&#xff0c;是对手工测试的一种补充; 自动化测试绝不能代替手工测试;多数情况…

【Mybatis】日常知识点随笔(持续更新)

目录 【K】Mybatis使用Select注解书写简单sql 【K】MySQL 数据类型与 Java 类型的对应关系 【K】Mybatis相同代码复用 1. 定义公共 SQL 片段 2. 引用公共 SQL 片段 3. 使用参数 4. 复用和组合 5. 注意事项 【K】mysql如何实现插入一条数据后立刻获取该数据自增长id进行…