C++之this指针

前言

        C++中对象模型和this指针是面向对象编程中的重要概念。对象模型描述了对象在内存中的布局和行为,包括成员变量、成员函数的存储方式和访问权限。this指针是一个隐含的指针,指向当前对象的地址,用于在成员函数中引用当前对象的成员变量和成员函数。对象模型和this指针的理解和应用,对于深入理解C++的面向对象特性和实现细节至关重要。

提出问题

        每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码。那么问题是:这一块代码是如何区分哪个对象调用自己的呢?

        C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象。this指针是隐含每一个非静态成员函数内的一种指针,this指针不需要定义,直接使用即可。

this指针的引出

引用自:【精选】[ C++ ] 一篇带你了解C++中隐藏的this指针_c++ this-CSDN博客

那我们首先来看一下,这段代码会输出什么结果呢?

#include<iostream>
using namespace std;class Date
{
public:void Display(){cout << _year << "-" << _month << "-" << _day << endl;}void SetDate(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year; // 年int _month; // 月int _day; // 日
};
int main()
{Date d1, d2;d1.SetDate(2022, 5, 11);d2.SetDate(2022, 5, 12);d1.Display(); // 2022-5-11d2.Display(); // 2022-5-12return 0;
}

输出结果: 

2022-5-11

2022-5-12 

分析:

我们首先可以通过汇编来看看,d1,d2调用的函数是否相同。

        我们可以发现,最终打印的时候调用的Display()(0A1500h)是同一个函数, 那么既然d1,d2调用的都是同一个函数,编译器如何知道d1是2022-5-11,d2是2022-5-12呢?Display()都访问的 _year,_month,_day。而且去公共代码区访问的Display(),这是为什么呢?

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

        在调用的时候也传的是各自的地址,这样就十分清晰明了了。这就是隐含的this指针。

        注意:我们不能显示的写出来,因为他是隐含的,我们不能抢了编译器的活。但是我们可以直接在类里面用。

将this指针存储的地址打印出来与类实例化后的对象地址作比较

#include<iostream>
using namespace std;class Date
{
public:void Display(){cout << this << endl;cout << _year << "-" << _month << "-" << _day << endl;}void SetDate(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year; // 年int _month; // 月int _day; // 日
};
int main()
{Date d1, d2;cout << "d1的地址为:" << &d1 << endl;cout << "d2的地址为:" << &d2 << endl;d1.SetDate(2023, 1, 1);d2.SetDate(2023, 1, 2);cout << "d1调用Display函数时输出结果:" << endl;d1.Display();cout << "d2调用Display函数时输出结果:" << endl;d2.Display(); return 0;
}

输出结果: 

this指针的用途

引用自:【C++漂流记】C++对象模型和this指针-CSDN博客

  • 当形参和成员变量同名时,可用this指针来区分
  • 在类的非静态成员函数中返回对象本身,可使用return *this

#include<iostream>
using namespace std;
class Person
{
public:Person(int age){//1、当形参和成员变量同名时,可用this指针来区分this->age = age;}Person& PersonAddPerson(Person p){this->age += p.age;//返回对象本身return *this;}int age;
};void test01()
{Person p1(10);cout << "p1.age = " << p1.age << endl;Person p2(10);p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);cout << "p2.age = " << p2.age << endl;
}int main() {test01();system("pause");return 0;
}

输出结果: 

分析:

        这段代码定义了一个Person类,其中包含一个构造函数和一个成员函数PersonAddPerson。test01函数创建了两个Person对象p1和p2,并测试了PersonAddPerson函数的功能。

        在构造函数中,使用了this指针来区分形参和成员变量。this指针指向当前对象,可以通过this->age来访问成员变量age。

        PersonAddPerson函数接受一个Person对象作为参数,将该对象的age加到当前对象的age上,并返回当前对象的引用。

        在test01函数中,首先创建了一个age为10的Person对象p1,并输出其age值。然后创建了另一个age为10的Person对象p2,并连续三次调用PersonAddPerson函数,每次传入p1作为参数。最后输出p2的age值。

        由于PersonAddPerson函数返回的是当前对象的引用,所以可以连续调用该函数。因此,p2的age值会依次增加30,最终输出为40。

空指针访问成员函数

        C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针。如果用到this指针,需要加以判断this指针是否为NULL,从而保证代码的鲁棒性。

示例:

#include<iostream>
using namespace std;//空指针访问成员函数
class Person {
public:void ShowClassName() {cout << "我是Person类!" << endl;}void ShowPerson() {if (this == NULL) {return;}cout << mAge << endl;}public:int mAge;
};void test01()
{Person* p = NULL;p->ShowClassName(); //空指针,可以调用成员函数p->ShowPerson();  //但是如果成员函数中用到了this指针,就不可以了
}int main() {test01();system("pause");return 0;
}

上述代码输出:

 我是Person类!

分析:

        这段代码定义了一个Person类,其中包含两个成员函数ShowClassName和ShowPerson,以及一个成员变量mAge。test01函数创建了一个空指针p,并尝试调用p的成员函数。

        在C++中,空指针是指向任何对象的指针,因此可以通过空指针调用成员函数。在ShowClassName函数中,没有使用this指针,所以可以正常调用,输出结果为"我是Person类!"。

        但是在ShowPerson函数中,使用了this指针来访问成员变量mAge。当空指针调用该函数时,this指针为NULL,因此访问成员变量时会出现错误。为了避免空指针访问,可以在函数体内通过判断this是否为NULL来提前返回,不执行后续代码。

        总结:空指针可以调用成员函数,但是如果成员函数中使用了this指针来访问成员变量,需要注意空指针的处理,避免出现错误。

若将ShowPerson()函数中的if判断this指针是否为NULL语句去掉,则会抛出异常,如下图所示。

关于this指针的总结

关于this指针,有以下几点总结:

1)this指针指向当前对象,可以访问当前对象的所有成员变量。包括private、protected、public。

2)this指针是const指针,一切企图修改该指针的操作,如赋值(改变指向)、增减都是不允许的!

3)this指针只有在成员函数中才有定义。因此,在创建一个对象后,也不能通过对象使用this指针。所以,我们也无法知道一个对象的this指针的位置(只有在成员函数里才有this指针的位置)。当然,在成员函数里,你是可以知道this指针的位置的(可以this获得),也可以直接使用的。

4)只有创建对象后,this指针才有意义。

5)static静态成员函数不能使用this指针。原因静态成员函数属于类,而不属于某个对象,所以static静态成员函数压根就没有this指针。

6)this在成员函数的开始执行前构造的,在成员函数的执行结束后清除。至于如何清除的,由编译器实现,程序员不关心。this是通过函数参数的首参数来传递的。
 


部分参考自:
https://blog.csdn.net/Goforyouqp/article/details/133470535
https://blog.csdn.net/tr_ainiyangyang/article/details/125638721

【精选】[ C++ ] 一篇带你了解C++中隐藏的this指针_c++ this-CSDN博客

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

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

相关文章

搭建伪分布式Hadoop

文章目录 一、Hadoop部署模式&#xff08;一&#xff09;独立模式&#xff08;二&#xff09;伪分布式模式&#xff08;三&#xff09;完全分布式模式 二、搭建伪分布式Hadoop&#xff08;一&#xff09;登录虚拟机&#xff08;二&#xff09;上传安装包&#xff08;三&#xf…

VMware Workstation里面安装ubuntu20.04的流程

文章目录 前言一、获取 desktop ubuntu20.04 安装镜像二、VMware Workstation下安装ubuntu20.041. VMware Workstation 创建一个新的虚拟机2. ubuntu20.04的安装过程3. 登录ubuntu20.044. 移除 ubuntu20.04 安装镜像总结参考资料前言 本文主要介绍如何在PC上的虚拟机(VMware W…

WordPress SMTP邮件发送插件 Easy WP SMTP

Easy WP SMTP是一款 WordPress 邮件发送插件&#xff0c;WordPress 中经常用到邮件发送&#xff0c;包括新注册用户的邮件通知、找回密码通知、评论回复通知等。因为云服务器默认不启用 SMTP功能&#xff0c;所以需要安装 SMTP插件来解决这个问题。 SMTP 主机&#xff1a;smtp.…

在云时代,我们该如何看待新的开源许可证?

目录 1、前言2、MongoDB与SSPL3、AGPL与SSPL许可证4、OSI Certified许可证5、背景总述 声明&#xff1a; 本文主要参考文章&#xff1a;https://www.infoq.cn/article/wXlSfiyvUUyxCcT4UZTQ 尊重原创&#xff0c;如有侵权&#xff0c;请联系删除 1、前言 开源许可证从最早的GPL…

javascript/python 笔记: folium feature group自动切换

1 python部分 python部分只能是静态的结果 1.1 导入库 import folium import math 1.2 数据 cell_lst表示基站位置&#xff0c;location_lst表示 用户实际位置&#xff08;均为伪数据&#xff09; cell_lst[[1.341505, 103.682498],[1.342751, 103.679604],[1.341505, 10…

YCSB and TPC-C on MySQL(避免重复load)

一、编译安装MySQL 下载mysql5.7.28源码 https://downloads.mysql.com/archives/community/ Select Operating System 选择 Source Code Select OS version 选择 All Operating Systems 选择带有boost的版本 安装系统包 apt -y install make cmake gcc g perl bison libai…

虹科分享 | 赋能物流机器人:CANopen通信如何发挥重要作用?

现代物流领域迅速融入了技术进步&#xff0c;特别是随着自主机器人的兴起&#xff0c;这一趋势越发明显。确保这些机器人在复杂的仓库环境中精确运行的一个关键方面是CANopen通信协议。该协议集成了各种组件&#xff08;电机、传感器、摄像头和先进的电池系统&#xff09;&…

vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播放卡花屏问题:

播放多个视频 <div class"video-box"><div class"video"><iframe style"width:100%;height:100%;" name"ddddd" id"iframes" scrolling"auto" :src"videoLeftUrl"></iframe>&l…

MySQL数据库操作(创建、修改、删除、查询)

MySQL查看或显示数据库&#xff08;SHOW DATABASES语句&#xff09; 在 MySQL 中&#xff0c;可使用 SHOW DATABASES 语句来查看或显示当前用户权限范围以内的数据库。查看数据库的语法格式为&#xff1a; SHOW DATABASES [LIKE ‘数据库名’]; 语法说明如下&#xff1a; 语法…

轴承寿命相关细节的研究

数据集PHM2012 介绍一下IEEE PHM2012数据集_phm2012轴承数据集-CSDN博客 标签如何设置的? 剩余寿命预测的标签设置_rul 标签_兔子牙丫丫的博客-CSDN博客 参考自刘硕师兄的毕业答辩PPT 图 4.9 训练数据的切分方法 数据段的重叠切分&#xff0c;不仅可以覆盖更多的标签数据…

任务调度框架-如何实现定时任务+RabbitMQ事务+手动ACK

任务调度框架 Java中如何实现定时任务&#xff1f; 比如&#xff1a; 1.每天早上6点定时执行 2.每月最后一个工作日&#xff0c;考勤统计 3.每个月25号信用卡还款 4.会员生日祝福 5.每隔3秒&#xff0c;自动提醒 10分钟的超时订单的自动取消&#xff0c;每隔30秒或1分钟查询…

golang 在 Mac、Linux、Window 下交叉编译

目录 交叉编译参数说明CGO_ENABLEDGOOS : 目标操作系统【darwin、linux、windows】GOARCH &#xff1a;目标架构【386、amd64、arm】 Mac 下编译&#xff0c;Linux / Windows 下执行Linux 下编译&#xff0c;Mac / Windows 下执行Windows 下编译&#xff0c;Mac / Linux 下执行…

Redis在分布式场景下的应用

分布式缓存 缓存的基本作用是在高并发场景下对应服务的保护缓冲 – 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; redis由于高强度性能采用内存 但是意味着丢失的风险单结点redis并发能力有限分布式服务中数据过多 依赖内存的redis 明显单机不…

WuThreat身份安全云-TVD每日漏洞情报-2023-10-18

漏洞名称:致远 OA XML 外部实体注入漏洞 漏洞级别:高危 漏洞编号:NULL 相关涉及:V5/G6 V6.0及以上全系列版本 漏洞状态:POC 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-26027 漏洞名称:XNSOFT NCONVERT 图像文件缓冲区溢出 漏洞级别:中危 漏洞编号:CVE-…

行为型模式-迭代器模式

迭代器模式是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素&#xff0c;不需要知道集合对象的底层表示。 意图&#xff1a;提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。 主要解决&#xff1a;不同的方式…

微信小程序自定义组件及投票管理与个人中心界面搭建

14天阅读挑战赛 人生本来就没定义&#xff0c;任何的价值都是自己赋予。 目录 一、自定义tabs组件 1.1 创建自定义组件 1.2 tabs.wxml 编写组件界面 1.3 tabs.wxss 设计样式 1.4 tabs.js 定义组件的属性及事件 二、自定义组件使用 2.1 引用组件 2.2 编写会议界面内容 …

DTI综述(更新中)

Deep Learning for drug repurposing&#xff1a;methods&#xff0c;datasets&#xff0c;and applications 综述读完&#xff0c;觉得少了点东西&#xff0c;自己写个DTI综述 Databases(包括但不限于文章中的) DATABASEDESCRIBEBindingDB有详细的drug信息和对应的target&a…

LeetCode 面试题 10.09. 排序矩阵查找

文章目录 一、题目二、C# 题解 一、题目 给定MN矩阵&#xff0c;每一行、每一列都按升序排列&#xff0c;请编写代码找出某元素。 示例: 现有矩阵 matrix 如下&#xff1a; [ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, …

推荐《中华小当家》

《中华小当家&#xff01;》 [1] 是日本漫画家小川悦司创作的漫画。该作品于1995年至1999年在日本周刊少年Magazine上连载。作品亦改编为同名电视动画&#xff0c;并于1997年发行播出。 时隔20年推出续作《中华小当家&#xff01;极》&#xff0c;于2017年11月17日开始连载。…

android 13.0 禁止app启动(不显示app列表)和允许app运行

1.前言 在13.0产品开发中,在进行教育平板的定制开发中,可以有需求要实现禁止app启动和允许app运行的接口,禁用后app后已安装的应用从桌面消失,只存在于系统设置内的应用列表里,无法调用。启用后,恢复正常使用,在桌面显示。对于app管理的都是由PackageManager来负责的,P…