先从一个程序的内存空间说起
#include<iostream>
using namespace std;
class A{
public:
void change()
{
b = 10;
c = 20;
}
private:
int b = 1;
int c = 2;
};
int main()
{
A a;
a.change(); //此处的对象a是存储在栈中的,但函数change的代码是在代码区的,那么调用change的
时候是怎么调用在栈中的成员变量b和c的呢?
return 0;
考虑方法1--在调用成员函数时将对象的地址传入,这样可以通过对象的地址来调用栈中的成员变量b和c
缺点:太繁琐,编译器本身自带该功能,成员函数隐含this指针。
class A{
public:
void change(A *d)
{
d->b = 10;
d->c = 20;
}
private:
int b = 1;
int c = 2;
};
int main()
{
A a;
a.change(&a);
return 0;
}
接下来用汇编来 探究编译器如何做到的
a.change();
00214040 lea ecx, [a] //调用成员函数时将对象a的地址赋值给ecx寄存器
00214043 call A::change(0211447h) //call函数
void change(void)
{
002146E0 push ebp
002146E1 mov ebp, esp
002146E3 sub esp, 0CCh
002146E9 push ebx
002146EA push esi
002146EB push edi
002146EC push ecx
002146ED lea edi, [ebp - 0CCh]
002146F3 mov ecx, 33h
002146F8 mov eax, 0CCCCCCCCh
002146FD rep stos dword ptr es : [edi]
002146FF pop ecx
00214700 mov dword ptr[this], ecx //将ecx存储的对象a地址赋值给[this]指针
b = 10;
00214703 mov eax, dword ptr[this] //this指针赋值给eax
00214706 mov dword ptr[eax], 0Ah //将10赋值给eax 此处eax即为对象a首地址
c = 20;
00FE470C mov eax, dword ptr[this] //this指针赋值给eax
00FE470F mov dword ptr[eax + 4], 14h //将20赋值给eax+4 此处eax+4即为对象b地址
}
00FE4716 pop edi
00FE4717 pop esi
00FE4718 pop ebx
00FE4719 mov esp, ebp
00FE471B pop ebp
00FE471C ret