'this'指针存储在计算机内存中的什么位置?
Where is the 'this' pointer stored in computer memory?
究竟在哪里是'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
是一个隐藏的额外参数,总是自动传递。
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);
注意,上面的转换是简化的,希望能使我的观点更清楚一些。不需要在注释中填满"哇,方法重载的编组在哪里,嗯?"我有异议。:)
将问题转换为"参数存储在哪里?",答案当然是"视情况而定"。:)
它通常在堆栈上,但也可以在寄存器中,或者编译器认为对目标体系结构有利的任何其他机制中。
其他答案已经很好地解释了典型编译器如何实现this
(通过将其作为隐式的第一个参数传递给函数)。
我认为看看c++ ISO规范对此的明确说明也是有用的。根据c++ 03 ISO规范,§9.3.2/1:
重要的是要注意在非静态(9.3)成员函数体中,关键字
this
是一个非左值表达式,其值为调用该函数的对象的地址。
this
是而不是一个变量——它是一个表达式,就像表达式1 + 2 * 3
是一个表达式一样。这个表达式的值几乎可以存储在任何地方。编译器可能把它放在堆栈上,作为隐式参数传递给函数,或者可能把它放在寄存器中,也可能把它放在堆中或数据段中。c++规范故意在这里给实现一些灵活性。
我认为"语言律师"的答案是"这完全是实现定义的,而且this
在技术上不是指针,而是一个计算为指针的表达式。"
希望这对你有帮助!
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
被视为该方法的常规参数。
this
是一个右值(你不能取它的地址),所以它没有(必然)占用内存。取决于编译器而目标体系结构,通常是在寄存器:0中在Sparc上运行,在Intel上运行带有MSVC的ECX等等。当优化器是它很活跃,甚至可以到处移动。我在不同的地方见过注册到MSVC)。
this
的行为更像是一个函数参数,因此将被存储在堆栈中,或者(如果体系结构的二进制调用约定允许的话)存储在寄存器中。
this
没有存储在一个定义良好的位置!它所指向的对象存储在某个地方,并且具有定义良好的地址,但地址本身没有特定的家庭地址。它在整个项目中传播。不仅如此,该指针还可以有多个副本。
在下面的虚构的init
函数中,对象注册自己以接收事件和计时器回调(使用虚构的事件源对象)。所以在注册之后,有两个额外的this
副本:
void foo_listener::init()
{
g_usb_events.register(this); // register to receive USB events
g_timer.register(this, 5); // register for a 5 second timer
}
在函数激活链中,也会有多个this指针的副本。假设我们有一个对象obj
并调用它的foo
函数。该函数调用同一对象的bar
函数,bar
调用另一个名为update
的函数。每个函数激活级别都有一个this
指针。它被存储在机器寄存器中,或者在函数激活的堆栈帧中的内存位置中。
- 这个返回元素位置的基于循环的函数有什么问题?
- 流中的输入位置和输出位置有什么区别?
- 当使用Lua作为嵌入式语言(比如c++)时,有什么简单/方便的方法可以找到变量在Lua中的定义位置吗
- 是否可以将要"ShellExecute"的文件包含在 dll 中?如果是这样,"ShellExecute"中的文件位置应该是什么?
- 我应该在服务模板中的什么位置添加自己的代码?
- pimpl 在 C++ 应用程序/库中的什么位置使用?任何例子
- Qt:交换QGraphicsRectItem位置的最佳方法是什么
- *的位置有什么区别:*变量与变量*
- 根据这些字符串输入在句子中的位置对这些字符串输入进行排序的更快方法是什么
- 库位于计算机中的什么位置
- 什么是 _mm_prefetch() 位置提示?
- 指针指向紧挨着对象末尾的位置是什么意思?
- Mac OS X 上的达尔文斯图书馆位置是什么?
- libc++ 标头位于 Mac OS X Mavericks 上的什么位置
- libtool的位置是什么,什么时候使用它
- 我的字节数组到十六进制字符串转换器有什么问题,或者为什么它在写入文件时会在某个位置后剪切符号?
- 对齐C++指针位置的目的是什么
- 在函数调用中,用大括号括起值文字evalue到什么位置
- 'this'指针存储在计算机内存中的什么位置?
- OpenGL如何知道它应该基于GL_ARRAY_BUFFER绘制顶点到什么位置