从汇编层理解CPPthis指针实现原理

当我们在C++中定义一个类时,编译器会把C++代码编译成汇编,但汇编中并没有类、类成员函数、类成员变量等概念,那在汇编层是如何来处理类的呢?

下面我们来看个简单例子:

class TestClass
{
public:
    int Sum()
    {
        return m_a+m_b;
    }
public:
    int m_a;
    int m_b;
};
int main()
{
    TestClass testClassObj;
    testClassObj.m_a = 5;
    testClassObj.m_b = 6;
    int result = testClassObj.Sum();
    return 0;
}

编译器会把上面的代码生成,语义类似下面的C代码

struct TestClass
{
    int m_a;
    int m_b;
};
INT TestClass_Sum(TestClass* this)
{
    return this->m_a +  this->m_b; 
}
int main()
{
    TestClass testClassObj;
    testClassObj.m_a = 5;
    testClassObj.m_b = 6;
    int result = TestClass_Sum(&testClassObj);
    return 0;
}

虽然C++中TestClass类把成员变量与成员函数写在了一起,但经过编译器处理后,本质上还是分开的,编译器会为成员函数(Sum函数)添加一个形参(this指针),通过这个this变量就能访问类对象里的成员变量。

下面来看下C++的类成员函数Sum是不是多了个形参this指针,且this指针指向对象本身:

我们前面详细分析过,函数的局部变量保存在栈上,

(1)testClassObj是main函数的局部变量,所以testClassObj保存在函数的栈上,而m_a是testClassObj对象的第一个局部变量,所以m_a的地址等于testClassObj对象的地址,

movl $0x5,-0x10(%rbp) 等价于 m_a=5;

movl $0x6,-0xc(%rbp) 等价于 m_b=5;

从而可知testClassObj的地址为-0x10(%rbp)

可知,testClassObj的地址,最后被传到了sum函数的栈上,保存的地址为$rbp-0x8,但Sum()函数的定义里是没有带形参的,所以这个新传入的对象就是编译器给我们加上的this指针,指向对象本身。这样就从汇编层证实了,编译器确实给类的成员函数添加了一个形参this指针。

本页共53段,1295个字符,2174 Byte(字节)