当前位置: 首页 > news >正文

从汇编的角度揭开C++ this指针的神秘面纱(下)

<接上篇>

我们接着来看一段C++的代码:

class A
{
public:int func(int j){return j +_i;}
private:int _i;    
};int main()
{A a;a.func(3);return 0;
}

这里定义了一个类A,在main函数中定义了A类的对像a。同时用a调用了成员函数func。我们来看一下main函数的汇编代码:

        pushq   %rbpmovq    %rsp, %rbpsubq    $16, %rsp         //rsp = rsp - 16leaq    -4(%rbp), %rax    //rax = rpb -4movl    $3, %esi          //esi = 3movq    %rax, %rdi        //rdi = raxcall    A::func(int)movl    $0, %eaxleaveret

在调用A::func之前,赋值了两个寄存器:rdi和rsi. 由上篇文单可知,这两个寄存器用于函数调用时,传递第1和第2个参数。那么这里我们有疑问:A::func(int)明明只有一个参数,为什么调用时,传递了两个参数呢?另一个参数是什么呢?答案就是:在调用成员函数时,this指针会做为一个隐含的参数传递给成员函数,并且是作为第一个参数。那么this指针又代表什么呢,this指针就是指向类对象的一个地址。对应上面汇编代码即是rbp-4。源代码a.func(3)相当于func(this, 3)也就是func(&a, 3); 

为了方便理解,我画出了main函数的栈空间,如下所示:

this指针存储的是a对象的地址。即rbp-4. 此时a对象里面只有一个int型的成员变量i, 占用4个字节。

接下来,我们分析一下func函数,汇编如下:

A::func(int):pushq   %rbpmovq    %rsp, %rbpmovq    %rdi, -8(%rbp)      //*(rbp-8) = rdimovl    %esi, -12(%rbp)     // *(rbp-12) = esimovq    -8(%rbp), %rax      // rax = *(rbp-8) movl    (%rax), %edx        // edx = *raxmovl    -12(%rbp), %eax     // eax = *(rbp-12)addl    %edx, %eax          // eax += edxpopq    %rbpret

func函数栈空间如下:  

  

func中会先分配栈空间rbp-8, rbp-12来存储传递过来的参数rdi(this)以及esi(3)。 然后根据这些参数来做下一步处理。

总结:

1)this指针的本质即对象的地址。

2)在调用类成员函数时,C++编译器会将其作为函数的第一个参数,传递给成员函数。

http://www.xdnf.cn/news/1046917.html

相关文章:

  • 【2】Redis 缓存击穿原理和解决方案
  • 小米MiMo系列:MiMo-7B-RL技术报告解读
  • 05-mcp-server案例分享-用豆包大模型 1.6 手搓文生图视频 MCP-server发布到PyPI官网
  • Python中shutil.rmtree()的目录删除能力详解
  • kicad运行时出错,_Pnext->_Myproxy = nullptr;访问内存出错
  • Spring Boot Web开发
  • 《拖延心理学》:深度剖析与应对指南​
  • 深入解析解释器模式:语言解析的优雅实现
  • Leetcode 刷题记录 16 —— 栈
  • 【git】 `git rm --cached *.pt` 删除了缓存,但这些大文件的历史记录仍然存在于Git历史
  • 《棒球百科》棒球怎么玩·棒球9号位
  • 岐黄慧问六月最终项目完成情况
  • 用于汽车毫米波雷达的四维高分辨率点云图像
  • 微软Bing正式推出AI视频生成工具:Bing Video Creator,由Sora技术驱动,限时免费体验!
  • 机器学习实验报告5-K-means 算法
  • ansible变量
  • 如何修改PyCharm的界面颜色(超详细)
  • vue2和vue3的底层逻辑原理、区别、用法以及应用优缺点
  • 大模型训练与推理显卡全指南:从硬件选型到性能优化
  • 软考 系统架构设计师系列知识点之杂项集萃(90)
  • AOP +ThreadLocal实现对接口监控
  • linux设置信号量系统参数
  • 【Dify系列】【Dify 核心功能】【应用类型】【三】【Agent】
  • Python 面向对象编程基础-类的创建与__init__实例化
  • [Java 基础]正则表达式
  • 第10章:Neo4j与其他技术集成
  • 图数据库neo4j部分用法浅讲
  • 基于SpringBoot和Leaflet的电影票房时序展示-以《哪吒2》为例
  • 6,TCP客户端
  • 【系统设计【3】】系统设计面试框架:从理论到实践的完整指南