this指针藏在哪里
在学习C++的过程中经常遇到一个神出鬼没的指针–this指针,本文就是揭秘一下this指针的实现机制。
C++是一种面向对象的编程语言,那么面向对象到底是一种怎样的实现机制呢?在《老码识途》这本书中,它说函数本身如同一个芯片,代码就是电路,局部变量就是存储元件,函数的代码只会操作自己的局部变量,不会操作其他函数,芯片的工作方式如同“能动体”,而C++的工作方式就像芯片一样,通过自己实现的函数去操作自己的数据,即将行为与数据合一,这就是封装的思想。
对于C++中的非静态成员函数,需要初始化一个对象,然后才能调用该函数,那么实例化的这个对象是怎样找到函数的地址呢?这里如果你熟悉C++的对象模型可能就比较清楚,每一个实例化的对象内存空间中都会保存成员变量与成员函数的地址,在调用成员函数的时候一定要告诉他是哪一个对象在调用该函数,而this指针就是该对象的地址,该对象在调用成员函数的时候就会把指向其本身的this指针传递给成员函数,这里是怎样传递的呢?
这里先给出结论,this指针在调用成员函数的过程中是作为第一个参数传递入的,该参数是保存在ecx寄存器中隐式传入的,下面就从反汇编的角度进行分析,IDE是Visual Studio 2019。
class TestObjClass {
private:
int a;
int b;
int c;
public:
void setC(int v);
};
void TestObjClass::setC(int v)
{
c = v;
}
int main()
{
TestObjClass t1;
t1.setC(2);
}
在调用setC()函数出打断点,然后查看其反汇编代码,可以看到首先将2压入栈中,接下来的lea语句将t1的地址赋值给寄存器ecx,下面进入setC()函数内部。
可以看到函数调用的反汇编代码,首先将ecx的值压入栈,然后又弹出,再赋值给this指针,由此可以看出,实例化的t1对象,首先将地址传递给ecx,然后在传入函数中。
这里你应该明白为什么在使用std::bind绑定一个类的成员函数实现回调的时候,传递this指针的作用了吧!
下面代码来自muduo网络库:
loop_->runInLoop(std::bind(&TcpConnection::shutdownInLoop, this));
在绑定TcpConnection类中的成员函数shutdownInLoop的时候,this指针作为第一个参数传入。