'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;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我调用成员函数add(),接收器对象隐式传递为'this'指针.凡被this存储在内存中?
unw*_*ind 78
最简单的方法是将其this视为隐藏的额外参数,并始终自动传递.
所以,一个虚构的方法,如:
size_t String::length(void) const
{
return strlen(m_string);
}
Run Code Online (Sandbox Code Playgroud)
实际上更像是在引擎盖下:
size_t String__length(const String *this)
{
return strlen(this->m_string);
}
Run Code Online (Sandbox Code Playgroud)
和一个电话:
{
String example("hello");
cout << example.length();
}
Run Code Online (Sandbox Code Playgroud)
变成这样的东西:
cout << String__length(&example);
Run Code Online (Sandbox Code Playgroud)
请注意,上面的转换是简化的,希望能让我的观点更加清晰.不需要用"whaaa填写评论,哪里是方法重载的编组,是吗?" - 请输入异议.:)
这将问题转化为"论据存储在哪里?",答案当然是"它取决于".:)
它通常在堆栈上,但它也可以在寄存器中,或者编译器认为对目标体系结构有益的任何其他机制.
tem*_*def 64
其他答案在解释典型编译器如何实现this(通过将其作为隐式第一个参数传递给函数)方面做得非常好.
我认为看看C++ ISO规范明确说明了什么也很有用.根据C++ 03 ISO规范,§9.3.2/ 1:
在非静态(9.3)成员函数的主体中,关键字
this是非左值表达式,其值是调用该函数的对象的地址.
重要的是要注意,this它不是变量 - 它是一个表达式,与表达式1 + 2 * 3是表达式的方式非常相似.允许将此表达式的值存储在任何地方.编译器可能将它放在堆栈上并将其作为隐式参数传递给函数,或者它可能将它放在寄存器中,并且可以想象它可以将它放在堆中或数据段中.C++规范故意在这里为实现提供了一些灵活性.
我认为"语言 - 律师"的答案是"这是完全实现定义的,而且this从技术上讲,它不是指针,而是一个计算指针的表达式."
希望这可以帮助!
Spo*_*ook 34
this通常作为方法的隐藏参数传递(不同调用约定的唯一区别是如何).
如果你打电话:
myClass.Method(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
编译器生成以下代码:
Method(&myClass, 1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
第一个参数实际上是指向的指针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;
}
Run Code Online (Sandbox Code Playgroud)
通过使用__stdcall我强制编译器通过堆栈传递所有参数.如果然后启动调试器并检查汇编代码,您将找到类似以下内容的内容:
myClass.Method(5);
00AA31BE push 5
00AA31C0 lea eax,[myClass]
00AA31C3 push eax
00AA31C4 call MyClass::Method (0AA1447h)
Run Code Online (Sandbox Code Playgroud)
如您所见,方法的参数通过堆栈传递,然后myClass的地址被加载到eax寄存器并再次被压入堆栈.换句话说,this被视为此方法的常规参数.
Jam*_*nze 18
this是一个右值(你不能取其地址),因此它根本不会(必然)占用内存.根据不同的编译器和目标体系结构,它往往会在寄存器中:在SPARC,ECX与MSVC英特尔,I0等当优化是积极的,它甚至可以左右移动.(我在与MSVC的不同寄存器中看到它).