'this'指针存储在计算机内存中的位置在哪里?
“this”指针究竟存储在内存中的什么位置? 它是在堆栈,堆中还是在数据段中分配的?
#include <iostream>
using namespace std;
class ClassA
{
int a, b;
public:
void add()
{
a = 10;
b = 20;
cout << a << b << endl;
}
};
int main()
{
ClassA obj;
obj.add();
return 0;
}
在上面的代码中,我调用成员函数add()
,并且接收者对象作为'this'指针隐式传递。 this
是存储在内存中的位置?
其他答案在解释典型编译器如何实现this
方面做了很好的工作(通过将其作为隐含的第一个参数传递给函数)。
我认为看看C ++ ISO规范明确地说明了这一点也很有用。 根据C ++ 03 ISO规范,§9.3.2/ 1:
在非静态(9.3)成员函数的主体中,关键字this
是一个非左值表达式,其值是调用该函数的对象的地址。
需要注意的是, this
不是一个变量 - 它是一个表达式,与表达式1 + 2 * 3
的表达方式大致相同。 该表达式的值允许存储在任何地方。 编译器可能会把它放在堆栈上,并将它作为一个隐式参数传递给一个函数,或者它可能会将它放入一个寄存器中,并且可以将它放入堆或数据段中。 C ++规范有意为这个实现提供了一些灵活性。
我认为“语言律师”的答案是“这完全是实现定义的,而且this
在技术上不是指针,而是一个评估指针的表达式。”
希望这可以帮助!
最简单的方法是将this
视为一个总是自动传递的隐藏的额外参数。
所以,一个虚构的方法,如:
size_t String::length(void) const
{
return strlen(m_string);
}
实际上更像这样:
size_t String__length(const String *this)
{
return strlen(this->m_string);
}
和一个像这样的电话:
{
String example("hello");
cout << example.length();
}
变成类似于:
cout << String__length(&example);
请注意,上述转换已经简化,希望能够让我的观点更清晰。 无需填写“whaaa,方法重载编组在哪里?”,请输入异议。 :)
这将问题转化为“存储参数的位置?”,答案当然是“取决于”。 :)
它通常在堆栈中,但也可能在寄存器中,或者编译器认为对目标架构有益的任何其他机制。
this
通常是作为方法的隐藏参数传递的(在不同调用约定中唯一的区别是如何)。
如果你打电话给:
myClass.Method(1, 2, 3);
编译器生成以下代码:
Method(&myClass, 1, 2, 3);
第一个参数实际上是指向this
的指针。
我们来看看下面的代码:
class MyClass
{
private:
int a;
public:
void __stdcall Method(int i)
{
a = i;
}
};
int main(int argc, char *argv[])
{
MyClass myClass;
myClass.Method(5);
return 0;
}
通过使用__stdcall
我强制编译器通过堆栈传递所有参数。 如果您然后启动调试器并检查汇编代码,您会发现如下内容:
myClass.Method(5);
00AA31BE push 5
00AA31C0 lea eax,[myClass]
00AA31C3 push eax
00AA31C4 call MyClass::Method (0AA1447h)
正如你看到的,方法的参数通过堆栈传递,然后myClass的地址被加载到eax寄存器并再次被压入堆栈。 换句话说, this
被视为这种方法的常规参数。