C++中 this指针、构造函数、析构函数

1.this指针

我们定义一个日期类来举例子

对于上述类,有这样一个问题,Date类中有Init和Print这两个成员函数,函数体中没有关于不同对象的区分,那d1调用函数的时候,编译器是如和来确定d1而不是d2呢?C++通过引入this指针解决了这种问题。

即C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
 

this指针的特性:

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

2. 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传

递,不需要用户传递

比如Print函数我们还可以写成这种

2.构造函数

C++中类有六个默认成员函数,这里我们先讲两种(构造函数和析构函数)

2.1构造函数的概念

在上述的Date类中,我们可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
 

2.2特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:

1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。

4. 构造函数可以重载。

class Date
{
public:
	//1.无参构造函数
	Date()
	{}

	//2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};



int main()
{
	Date d1;//调用无参构造函数
	//注意,如果通过无参构造函数创建对象时,不用带括号,否则就成了函数声明
	Date d2(2024,1,28);//调用有参构造函数
	d1.Print();
	d2.Print();
	return 0;
}

如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦

用户显式定义编译器将不再生成。

我们将Date类中的构造函数屏蔽后代码通过了编译,倘若我们将构造函数展开就会编译失败,这就是因为一旦显式定义任何构造函数,编译器将不再生成默认构造函数,然后我们的调用方式没有传参,所以编译就会不通过。

但是关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d1对象调用了编译器生成的默认构造函数,但是d1对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用??

解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。

所以C++98规定默认构造函数会对自定义类型构造,没有规定必须给内置类型构造,但C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

如上图所示,在声明内置类型的时候直接赋上默认值。

最后:

无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
 

3.析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
析构函数是特殊的成员函数,其特征如下:

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

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。

上述的场景中,我们定义了一个对象d,没有对它进行任何操作,在它生命周期结束的时候就自动调用了析构函数。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux线程安全

Linux线程安全 Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex互斥量的接口 可重入VS线程安全常见锁概念死锁的四个必要条件 Linux线程同步条件变量 Linux线程互斥 进程线程间的互斥相关背景概念 临界资源和临界区 进程之间如果要进行通信我们需要先创建第三方资源&a…

虚拟机安装Centos8.5

记得看目录哦&#xff01; 附件1. 新建虚拟机2. 安装Centos8.5 附件 安装包自行下载 https://mirrors.aliyun.com/centos/8/isos/x86_64/ 1. 新建虚拟机 2. 安装Centos8.5 启动虚拟机–选择第一个install Centos8.5 记得接收许可证

VUE3子表格嵌套分页查询互相干扰的问题解决

VUE3在表格中嵌套子表格子表格的分页查询互相干扰的问题解决 简单嵌套 如果不需要做子表格的分页查询&#xff0c;那么可以直接在主表格中嵌套子表格&#xff0c;有两种方式&#xff1b;一种是主表格加载的同时加载子表格数据&#xff0c;另一种是点击展开时加载子表格数据&…

(2024,初始化原型嵌入,扩散模型微调,类别特征正则化,对象特定损失)使用原型嵌入对文本到图像扩散进行对象驱动的单样本微调

Object-Driven One-Shot Fine-tuning of Text-to-Image Diffusion with Prototypical Embedding 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 方法 3.1 概述 3.2 LDM …

面试官要你介绍项目,怎么说?

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Golang数据结构性能优化实践

仅仅通过对struct字段重新排序&#xff0c;优化内存对齐方式&#xff0c;就可以获得明显的内存和执行效率提升。原文: How to Speed Up Your Struct in Golang Mike Pexels 如果你有Golang开发经验&#xff0c;一定定义过struct类型。 但可能你不知道&#xff0c;通过简单的重新…

数据据库八之 视图、触发器、事务

【零】数据准备 【1】创建表 &#xff08;1&#xff09;部门表 d_id是部门的编号d_name是部门的名字 # 确保表不存在 drop table if exists department; # 创建表 create table department( d_id int auto_increment primary key, d_name varchar(6) )auto_increment 501 …

【linux|java应用报错】Cannot allocate memory

启动一个java应用报Cannot allocate memory&#xff0c;并且会生产一个hs_ess_pid.log文件。 文件内容为&#xff1a; #内存不足&#xff0c;Java运行时环境无法继续。 #本机内存分配&#xff08;mmap&#xff09;无法映射4294967296字节以提交保留内存。 【排查】 1、尝试使…

Mysql-事务(隔离级别,事务底层原理,MVCC)

什么是事务&#xff1f;有哪些特性&#xff1f; 事务&#xff1a;事务指的是逻辑上的一组操作&#xff0c;组成这组操作的各个单元要么全都成功&#xff0c;要么全都失败。 事务特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a; 原子性是指事务是一个不…

Python tkinter (11) —— Frame控件

本文主要是Python tkinter Frame框架控件介绍及使用简单示例。 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkint…

大健康行业千城万企信用建设工作启动大会在京召开

9月19日&#xff0c;为响应商务部、中宣部、国家发改委等13个部门共同举办的“诚信兴商宣传月”活动&#xff0c;中国国际电子商务中心所属北京国富泰信用管理有限公司联合北京华商国医堂集团及旗下东方岐黄商学院&#xff0c;北京华商国医堂中医药研究院举办的共筑信用月&…

Mov转MP4怎么转换?如何播放mov视频?

MOV文件格式的使用场景 MOV文件格式以其支持多种媒体数据类型的特性而闻名&#xff0c;包括视频、音频、文本、动画等。它常用于存储包含视频剪辑、电影、音频轨道等多媒体元素的文件。由于其在质量和编辑方面的优越性&#xff0c;MOV文件在电影制作、广告宣传、多媒体演示等领…

阿里二面:SpringBoot同时可以处理多少个请求?直接懵了。。。

SpringBoot以其简洁高效的开发方式和强大的内嵌容器特性&#xff0c;为开发者提供了构建高性能后端服务的便利。然而&#xff0c;当面临高并发场景时&#xff0c;理解并合理配置Spring Boot应用以达到最佳的并发处理能力至关重要。在Spring Boot中&#xff0c;应用程序对HTTP请…

Docker最新超详细版教程通俗易懂(基础版)

Docker概述 概念&#xff1a;容器虚拟化技术&#xff0c;系统平滑移植&#xff0c;解决了运⾏环境和配置问题的软件容 器&#xff0c;⽅便做持续集成并有助于整体发布的容器虚拟化技术 意义&#xff1a;Docker的出现使得Docker得以打破过去程序即应⽤的观念&#xff0c;透过…

Flink中的时间语义和TTL

时间语义 事件时间&#xff08;Event Time&#xff09; 事件时间是数据生成的时间&#xff0c;是数据流中每个元素或者每个事件自带的时间属性&#xff0c;一般是事件发生的时间&#xff0c;在实际项目中作为前端的一个属性嵌入。在理想情况下&#xff0c;数据应当按照事件时…

TeX:一款功能强大的Telegram安全监控与管理工具

关于TeX TeX是一款功能强大的Telegram安全监控与管理工具&#xff0c;该工具专为Telegram设计&#xff0c;可以实现针对Telegram的安全监控与管理。 TeX旨在帮助安全研究人员、调查人员和执法人员收集和处理针对网络犯罪分子的取证信息&#xff0c;其中包括网络犯罪、欺诈攻击…

vue3-深入组件-透传属性

透传属性 &#xff08;透传 attribute&#xff09; 什么是透传属性&#xff08;透传 attribute&#xff09;? 传递给一个组件&#xff0c;却没有被该组件声明为 props 或 emits 的 attribute 或者是事件监听器&#xff0c;例如 class style id 等。 属性继承 当一个组件以单…

STM32 1-5

目录 STM32简介 点亮PC13LED GPIO LED闪烁 LED流水灯 按键控制LED 光敏传感器控制蜂鸣器 OLED调试工具 OLED显示 EXTI外部中断 对射式红外传感器计次 旋转编码器计次 继续 STM32简介 点亮PC13LED main.c #include "stm32f10x.h" // D…

【linux】复制cp和硬连接、软连接的区别? innode 关系?

1.命令&#xff1a; cp -r [源文件或目录] [目的目录] #复制 ln -s [被链接的文件] [链接的目录/名称] #软连接 ln [被链接的文件] [链接的目录/名称] #硬连接 注&#xff1a;cp -r 会把所有source当作普通文件&#xff08;regular文件&#xff09;&#x…

代码随想录算法训练营第35天 | 860.柠檬水找零 406.根据身高重建队列 452.用最少数量的箭引爆气球

柠檬水找零 局部最优&#xff1a;收到20元时优先找零10元5元&#xff0c;不够再找零3个5元&#xff0c;因为5元可以找零20和10&#xff0c;更有用。全局最优&#xff1a;完成所有的找零。 class Solution { public:bool lemonadeChange(vector<int>& bills) {int fi…