从汇编的角度揭开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   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp         //rsp = rsp - 16
        leaq    -4(%rbp), %rax    //rax = rpb -4
        movl    $3, %esi          //esi = 3
        movq    %rax, %rdi        //rdi = rax
        call    A::func(int)
        movl    $0, %eax
        leave
        ret

在调用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   %rbp
        movq    %rsp, %rbp
        movq    %rdi, -8(%rbp)      //*(rbp-8) = rdi
        movl    %esi, -12(%rbp)     // *(rbp-12) = esi
        movq    -8(%rbp), %rax      // rax = *(rbp-8) 
        movl    (%rax), %edx        // edx = *rax
        movl    -12(%rbp), %eax     // eax = *(rbp-12)
        addl    %edx, %eax          // eax += edx
        popq    %rbp
        ret

func函数栈空间如下:

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

总结:

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

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

相关推荐
Chester_19994 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
EXI-小洲5 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员5 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
小灰灰搞电子5 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化6 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
2601_961901706 小时前
SpringBoot使用Nacos进行application.yml配置管理
java·spring boot·spring
何以解忧,唯有..7 小时前
LangChain 工具调用(Tool Calling)实战指南
java·前端·langchain
QQ_21696290967 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端
学习星球8 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
前端 贾公子8 小时前
第09章:上下文与记忆 (2)
java·服务器·前端