从CPU的视角看C++的构造函数和this指针

从汇编角度,清晰的去看构造函数和this指针到底是个什么东西呢?也许可以解决你的一点小疑问

首先写一个很简单的代码demo:

class A{
public:int a;A(){;}void seta(int _a){a=_a;}A* getA(){return this;}
};int fun1(int px){return px;
}int main(){A aa;aa.seta(8); aa.getA();
}

mov rbp, rsp:设置新的基址指针,指向当前栈帧。

mov QWORD PTR [rbp-8], rdi:将 this 指针(存储在 rdi 中)保存到栈上。

在seta中的部分汇编:

mov rax, QWORD PTR [rbp-8]:将 this 指针的值加载到 rax 中。

mov DWORD PTR [rax], edx:将 edx(即 _a 的值)存储到 this->a 中。

我们从类成员函数和构造函数中都能看到 两句关于参数的汇编,同理普通函数中px参数也有着相同的汇编,那么很显然,对于cpu而言,this指针仅仅是一个参数而已。C++语法糖对于this做了隐藏处理,因此我们在使用的时候才会无感。

而这个有这个this往往可以认为函数的完整使用是这样:

    A aa;aa.seta(8); ====A::seta(&aa,8) 当然这么调用是错误的,看着很像类静态函数

this 指针的创建

  • 函数调用前创建:当成员函数被调用时,this 指针在调用成员函数之前被设置为当前对象的地址。也就是说,在成员函数执行之前,this 指针已经被创建并指向调用该函数的对象。

this 指针的销毁

  • 函数调用结束后销毁:在成员函数执行完毕并返回后,this 指针的生命周期就结束了。因为 this 只是一个指向对象的指针,当函数返回时,不再需要这个指针,函数调用上下文会自动清理这个隐式参数。

 

学习C++的友友大概率会知道这么一句话:静态成员函数不属于类的某个具体对象,而是属于整个类。这意味着静态成员函数不能访问非静态成员变量和成员函数,因为它们没有 this 指针。针对这句话我们也可以通过cpu视角进行观察

而this 指针的存在条件

  • 对象实例调用:只有当对象实例调用非静态成员函数时,this 指针才会被传递给该函数。
  • 隐式参数:在非静态成员函数内部,编译器会自动添加一个隐式的 this 指针参数,用于引用调用该函数的对象

观察上图,你就会看到 静态成员函数中没有this指针,即也就没法去调用相关的成员函数和数据,如果我们想要通过静态成员函数去调用对象相关的数据,可以通过黄色框框的这种写法。你会发现这种写法的汇编同成员函数的汇编相同,也就是说this存的就是传递进去的这个对象的地址。

也就有了成员函数的完整版应该是:void setp(A* this,int p);是不是看着参数和示例第二个静态成员函数一样~

cpu眼中构造函数与普通函数没有任何区别:

通过上面的汇编也能看明白,构造含有this指针,且对于cpu来说他与普通函数是相同的

派生类构造函数总会调用基类的构造函数

  • mov QWORD PTR [rbp-8], rdi:将 this 指针(在 rdi 中)保存到局部变量中。
  • mov rax, QWORD PTR [rbp-8]:将 this 指针从局部变量中加载到 rax 中。
  • mov rdi, rax:将 this 指针(现在在 rax 中)移动到 rdi 中,以便调用基类构造函数时使用。
  • call A::A() [base object constructor]:调用基类 A 的构造函数。此时,this 指针指向 B 对象,但调用的是 A 的构造函数,因此它会正确初始化 A 的部分。
  • mov rax, QWORD PTR [rbp-8]:再次将 this 指针从局部变量中加载到 rax 中。
  • mov DWORD PTR [rax+4], 1:将 1 赋值给 this->a。这里的 [rax+4] 指的是b 位于对象内偏移量 4 的位置。 (因为B继承A,B所以内存结构上,前四个字节是A.a ,然后才是B.a ,所以是移动到偏移4位置之后在赋值)

 

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

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

相关文章

【FreeRTOS】同步互斥与通信 有缺陷的同步示例

目录 1 同步互斥与通信1.1 同步互斥与通信概述1.2 同步与互斥的概念1.3 同步的例子:有缺陷1.4 freertos.c源码3. 互斥的例子:有缺陷4. 通信的例子:有缺陷5. FreeRTOS的解决方案 1 同步互斥与通信 1.1 同步互斥与通信概述 参考《FreeRTOS入门…

搞钱四步:干活、出名、破圈、整合

搞钱这事儿,说起来有四步:干活、出名、破圈、整合。 咱们现在这个时代,谁要是能把自尊心放一边,勇敢站到舞台上展示才华,变现那是分钟的事儿。 只要你敢承认自己想要财富,并且不停地使用正确的方法论&…

python语句前面有一个$是什么意思

“$”是汇编语言中的一个预定义符号,等价于当前正汇编到的段的当前偏移值。例如:指令“jmp $3”中的“$”表示当前这条指令在代码段中的偏移量。 代表当前指令的地址,如: data segment str1 db a,b,c,d leng equ $-str 就是当前地…

JVM专题之性能优化

运行时优化 方法内联 > 方法内联,是指 **JVM在运行时将调用次数达到一定阈值的方法调用替换为方法体本身** ,从而消除调用成本,并为接下来进一步的代码性能优化提供基础,是JVM的一个重要优化手段之一。 > > **注:** > > * **C++的inline属于编译后内联,…

数据库实训复习(1)

目录 一、关于表结构的相关操作(与表中字段的数据操作有区别) (1)往已有的表中添加字段 (2)修改表中已有字段的数据类型 (3)修改已有的表中的字段名和字段类型 (4&a…

TopK问题与堆排序

目录 TopK问题: 定义: 应用场景: 搜索引擎: 推荐系统: 数据分析: 数据挖掘: TopK问题初阶:(数据量较小情况) TopK问题进阶:(…

知名品牌因商标痛失市场:114家直营店山寨店7000多家!

奶茶知名品牌“鹿角巷”当年红遍大江南北,是最早的新茶饮品牌,但是当年商标注册存在问题,被同行奶茶品牌抢占了先机,发声明“对大陆商标注册细则不详,在商标注册过程中让假店钻了法律空档”,最夸张的时候全…

qml required property

目录 前言 示例代码 创建一个自定义组件(MyComponent.qml) 使用自定义组件(main.qml) 解释 运行效果 运行时错误示例 前言 在 QML 中,你可以使用 required 关键字来声明一个属性是必需的。这意味着在创建该对象…

如何用Python向PPT中批量插入图片

办公自动化办公中,Python最大的优势是可以批量操作,省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道,把图片插入到PPT当中的固定位置是一个非常繁琐的操作,往往调整图片时耗费大量的时间和精力。如何能省时省力插…

【数据结构】使用C语言 从零实现一个栈的数据结构

栈 什么是栈?栈是一种特殊的线性表,它只能在在表尾进行插入和删除操作。 栈的底部称为栈底,顶部称为栈顶,所有的操作只能在栈顶进行,也就是说,被压在下方的元素,只能等待其上方的元素出栈之后…

LeetCode-简单-回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数 是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,…

windows启动Docker闪退Docker desktop stopped

Windows启动Docker闪退-Docker desktop stopped 电脑上很早就安装有Docker了,但是有一段时间都没有启动了,今天想启动启动不起来了,打开没几秒就闪退,记录一下解决方案。仅供参考 首先,参照其他解决方案,本…

Ubuntu20安装mysql方法,适用于wsl

itopen组织1、提供OpenHarmony优雅实用的小工具2、手把手适配riscv qemu linux的三方库移植3、未来计划riscv qemu ohos的三方库移植 小程序开发4、一切拥抱开源,拥抱国产化 一、Ubunt20安装mysql 适用于wsl中安装mysql sudo apt update# 查看可使用的安装包…

【刷题汇总--游游的you、腐烂的苹果、孩子们的游戏(圆圈中最后剩下的数)】

C日常刷题积累 今日刷题汇总 - day0051、游游的you1.1、题目1.2、思路1.3、程序实现 - 蛮力法1.4、程序实现 - 贪心(优化) 2、腐烂的苹果2.1、题目2.2、思路2.3、程序实现 - bfs 3、孩子们的游戏(圆圈中最后剩下的数)3.1、题目3.2、思路3.3、程序实现 -- 环形链表3.4、程序实现…

2个方法教你轻松移除pdf文件编辑限制

PDF是一种常见的办公文档格式,常用于文件共享和保护。然而,有时候我们需要编辑PDF文件中的内容,但受到了编辑限制。本文将介绍一些有效的方法,帮助您解除PDF的编辑限制,轻松进行编辑和修改。 一、通过密码取消PDF“限制…

雷电模拟器报错remount of the / superblock failed: Permission denied remount failed

报错截图 解决方法 打开设置 设置配置system.vmdk可写入 解决

Transformer和Mamba强强结合!最新混合架构全面开源,推理速度狂飙8倍

最近发现,将Mamba和Transformer模块混合使用,效果会比单独使用好很多,这是因为该方法结合了Mamba的长序列处理能力和Transformer的建模能力,可以显著提升计算效率和模型性能。 典型案例如大名鼎鼎的Jamba:Jamba利用Tr…

ELK优化之Elasticsearch

目录 1.ELK优化 2.优化 ES 索引设置 2.1 优化 fsync 2.2 优化 refresh 2.3 优化 merge 2.4 优化设置 2.5 打开索引 3.优化线程池配置 3.1 优化的方案 4.锁定内存,不让 JVM 使用 Swap 5.减少分片数、副本数 6.ES优化总结 1.ELK优化 ELK优化可以围绕着 li…

Python统计实战:时间序列分析之简单指数平滑和Holt指数平滑

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能,从而更快地掌握解决问题所需的能力。 (以下练习题来源于《统计学—基于Python》。请在Q群455547227下载原始数据。) 练习题 下表是某只股票…

二维平面无中心点的聚类算法

问题描述 二维平面上有许多点p(x , y),按照彼此之间的欧式距离进行分为若干个集合。若点p1(x1, y1)与点p(x2, y2)之间距离小于d,则认为二者是邻居。 算法思路 给数据集的点进行编号,顺序遍历这些点,找出当前点的邻居,记住已经遍…