<接上篇>
我们接着来看一段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++编译器会将其作为函数的第一个参数,传递给成员函数。