【C++】this指针讲解超详细!!!
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍
文章目录
- 一、this指针引入
- 1.引入
- 2.分析
- 3.图示
- 二、 this指针存在哪里?
- 三、this指针的特性
- 四、 案例分析
一、this指针引入
1.引入
#include<iostream>
using namespace std;
class Data
{
public:void Init(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()
{
//创建Data的对象1Data d1;d1.Init(1999, 1, 1);
//创建Data的对象2Data d2;d2.Init(2023, 1, 1);
//调用print函数d1.print();d2.print();return 0;
}
打印结果:
2.分析
上面代码运行结果中,为什么两个对象调用同一个函数能打印出不同的日期呢?或者说同一个函数如何做到结果不同呢?
简单说是通过C++的一个关键字this来实现的。
上面代码着编译后,就成了如下:
#include<iostream>
using namespace std;
class Data
{
public:void Init(int year,int month,int day){_year = year;_month = month;_day = day;}void print(Data* this){cout << this->_year << ":" << this->_month << ":" << this->_day << endl;}
private:int _year;int _month;int _day;
};int main()
{
//创建Data的对象1Data d1;d1.Init(1999, 1, 1);
//创建Data的对象2Data d2;d2.Init(2023, 1, 1);
//调用print函数d1.print(&d1);d2.print(&d2);return 0;
}
当不同对象调用print函数时,其实在底层是传了一个Data*类型的指针this。
void print(Data* this){cout << this->_year << ":" << this->_month << ":" << this->_day << endl;}
> 如下图所示:
其实底层还是和C语言函数调用一样,也需要传参,只不过C++的编译器为我们默默做了这些事情,让我们用起来更方便。但是,不能显示的去写出this的相关实参和形参,需要注意的是在类中可以使用this->。
3.图示
this本质是一个形参,哪个对象调用他,就指向哪个对象。
二、 this指针存在哪里?
下图是代码在vs2019编译器下执行的汇编语句
。
当执行d1.Init(1999, 1, 1);时,先是将三个实参进行压栈。其实实参应该有4
个,还有一个隐藏的this指针
。
(1)000426EF push 1
(2)000426F1 push 1
(2)000426F3 push 7CFh
通过这一句(4)000426F8 lea ecx,[d1]
我们可以清晰的看到this指针在vs编译器下,是存到了寄存器( ecx)。
其实,this指针存在的位置一般是在栈帧上,不同的编译器有所不同,例如vs2019就是存在寄存器上。
因为this指针,占用内存小并且需要频繁使用,所以,将它放到寄存器里能大大提升运行效率。
三、this指针的特性
- this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
- 只能在“成员函数”的内部使用
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。 - this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递
四、 案例分析
下面代码会出现问题吗?
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
前提知识
-
p的意义有两个。1.p是A类一个对象的指针,p->print(),对象的指针调用函数肯定是找成员函数中的,也就是说编译的时候检查语法,让我们知道print函数是A类中的成员函数,起到定位语法作用。
-
p指针为空,相当于this指针为空。
-
成员变量存储在对象中
-
成员函数没有存储在对象中
-
p->Print();说明调用的是A类中的成员函数
调用print函数与this指针无关,只有访问成员变量时才会使用到this。
因为函数是在编译链接的时候找的(本质是找函数的地址),上一篇详细讲过对象的存储方式中讲过,成员函数存在公共区域的函数表(函数表中存有成员函数的地址)查找修饰后的函数名【因为C++支持重载,所以需要对函数名 进行特殊的修饰】来进行查找。
所以,代码运行正常。
看下面代码:
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}
printA函数中使用了成员变量,编译时printA函数底层如下形式:
void PrintA(Data* this)
{
cout<<this_a<<endl;
}
mian函数中是
p->PrintA(p);
将p传给了this指针。
_a=>this_a
,需要访问this指针,但此时this指针为空。
所以,运行崩溃!
相关文章:

【C++】this指针讲解超详细!!!
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
系统讲解java中list.stream()的用法
在Java 8及以后的版本中,引入了新的Stream API,这个API提供了一组新的操作方法,可以便捷 地对Java集合进行过滤、映射、排序、分组等操作。 在Stream API中主要分中间操作,和终止操作 中间操作是对流进行处理但不产生最终结果的…...

字节面试:请说一下DDD的流程,用电商系统为场景
说在前面 在40岁老架构师 尼恩的读者交流群(50)中,最近有小伙伴拿到了一线互联网企业字节、如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题: 谈谈你的DDD落地经验? 谈谈你对DDD的理解&…...

第26章_事务概述与隔离级别
文章目录 事务事务的特征事务的控制语句事务的生命周期事务的执行过程 ACID特性原子性一致性隔离性持久性 隔离级别不同隔离级别并发异常脏读不可重复读幻读区别 总结 事务 (1)事务的前提:并发连接访问。MySQL的事务就是将多条SQL语句作为整…...
合肥工业大学网络安全实验IP-Table
✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :hfut实验课设 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。能力再大,你不行动,只能看别人成功!没有人会关心你付出过多少…...

Docker本地镜像发布到阿里云或私有库
本地镜像发布到阿里云流程 : 1.自己生成个要传的镜像 2.将本地镜像推送到阿里云: 阿里云开发者平台:开放云原生应用-云原生(Cloud Native)-云原生介绍 - 阿里云 2.1.创建仓库镜像: 2.1.1 选择控制台,进入容器镜像服…...

使用openvc进行人脸检测:Haar级联分类器
1 人脸检测介绍 1.1 什么是人脸检测 人脸检测的目标是确定图像或视频中是否存在人脸。如果存在多个面,则每个面都被一个边界框包围,因此我们知道这些面的位置 人脸检测算法的主要目标是准确有效地确定图像或视频中人脸的存在和位置。这些算法分析数据…...
Netty心跳检测
文章目录 一、网络连接假死现象二、服务器端的空闲检测三、客户端的心跳报文 客户端的心跳检测对于任何长连接的应用来说,都是一个非常基础的功能。要理解心跳的重要性,首先需要从网络连接假死的现象说起。 一、网络连接假死现象 什么是连接假死呢&…...

【leaflet】1. 初见
▒ 目录 ▒ 🛫 导读需求开发环境 1️⃣ 概念概念解释特点 2️⃣ 学习路线图3️⃣ html示例🛬 文章小结📖 参考资料 🛫 导读 需求 要做游戏地图了,看到大量产品都使用的leaflet,所以开始学习这个。 开发环境…...
数据结构与算法(Java版) | 详解十大经典排序算法之一:冒泡排序
前面虽然大家已经知道了多种不同的排序算法,但是我一直都没来得及给大家讲,所以,从这一讲起,我就要开始来给大家详细讲解具体的这些排序算法了。 下面,我们先来看第一个最常见的排序,即冒泡排序。 冒泡排…...
轻量封装WebGPU渲染系统示例<24>- Rendering Pass Graph基本用法(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PassNodeGraphTest.ts 此示例基于此渲染系统实现,当前示例TypeScript源码如下: class PassGraph extends WGRPassNodeGraph {constructor() { super();…...

开设自己的网站系类01购买服务器
开始建设自己的网站吧! 编者买了一个服务器打算自己构建一个网站,用于记录生活。网站大概算是一个个人博客吧。记录创建过程的一些步骤 要开设自己的网站,需要执行以下关键步骤 以下只是初步列出了建立自己的网站的大概步骤,后…...

FTP、NFS、SAMBA系统服务一
一、rsync托管xinetd 1、为什么要进行服务托管 独立服务:独立启动脚本 ssh ftp nfs dns ... 依赖服务: 没有独立的启动脚本 rsync telnet 依赖xinetd服务(独立服务) 2、如何将rsync托管给xinetd服务去管理? 第一步࿱…...

transfomer模型——简介,代码实现,重要模块解读,源码,官方
一、什么是transfomer Transformer是一种基于注意力机制(attention mechanism)的神经网络架构,最初由Vaswani等人在论文《Attention Is All You Need》中提出。它在自然语言处理(NLP)领域取得了巨大成功,特…...
队列(Queue):先进先出(FIFO)的数据结构
队列是一种基本的数据结构,用于在计算机科学和编程中管理数据的存储和访问。队列遵循先进先出(First In, First Out,FIFO)原则,即最早入队的元素首先出队。这种数据结构模拟了物理世界中的队列,如排队等待服…...

吃透 Spring 系列—AOP部分
目录 ◆ AOP 简介 - AOP的概念 - AOP思想的实现方案 - 模拟AOP的基础代码 - AOP相关概念 ◆ 基于xml配置的AOP - xml方式AOP快速入门 - xml方式AOP配置详解 - xml方式AOP原理剖析 ◆ 基于注解配置的AOP - 注解方式AOP基本使用 - 注解方式AOP配置详解 - 注解…...
redis 问题解决 2
1.4 数据存储 1、Redis 的数据过期策略是什么? Redis的数据过期策略包括两种机制:被动删除和主动删除。 被动删除: 当某个键被访问时,如果发现这个键已经过期,Redis会立即删除这个键。这意味着如果一个过期的键从未被访问,它就不会被自动删除。这是一种惰性删除策略。主…...
Spring Boot 校验用户上传的图片文件
图片上传是现代应用中非常常见的一种功能,也是风险比较高的一个地方。恶意用户可能会上传一些病毒、木马。这些东西不仅严重威胁服务器的安全还浪费了带宽,磁盘等资源。所以,在图片上传的接口中,一定要对用户上传的文件进行严格的…...

【springboot配置项动态刷新】与【yaml文件转换为java对象】
文章目录 一,序言二,准备工作1. pom.xml引入组件2. 配置文件示例 三,自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四,yaml文件转换为java对象1. 无法使…...

JS移动端触屏事件
在我们PC端中有许多的事件,那我们在移动端有没有事件呢?让我为大家介绍一下移动端常用的事件,触屏事件 触屏事件 touch (也称触摸事件),Android 和IOS 都有 touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...

如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...
RLHF vs RLVR:对齐学习中的两种强化方式详解
在语言模型对齐(alignment)中,强化学习(RL)是一种重要的策略。而其中两种典型形式——RLHF(Reinforcement Learning with Human Feedback) 与 RLVR(Reinforcement Learning with Ver…...

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码
在建材矿粉磨系统中,开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议:Modbus和Ethernet IP。Modbus是一种串行通信协议,广泛应用于工业控制系统中。它简单、易于部署和维护…...