为什么指向虚函数表的指针会影响类的大小,而这个指针不影响类的大小?this 指针放在哪里以及何时为其分配内存?
5 回答
它作为隐式参数传递,因此它不存储在对象内部。当你写:
struct X
{
void f( int i );
};
X x;
x.f( 42 );
你可以这样想:
void f( X* const this, int i ); // of course this would be illegal as "this" is a keyword
f( &x, 42 );
所以this
-pointer 来自调用方法的位置。
指向虚函数表的指针存储在对象中,但this
实际上是成员函数的隐藏参数。实际上,当你有这个时:
class X
{
void foo(int bar) const;
};
int main()
{
X x;
x.foo(7);
}
然后编译器会将其隐式转换为类似这样的内容(伪代码):
class X
{
static void foo(const X * const this, int bar);
};
int main()
{
X x;
X::foo(&x, 7);
}
请注意,我仅出于说明目的显示伪代码。你可以在概念上这样想象它,但这并不是实际发生的事情。
Like 'this' pointer, the vptr depends a instance not the class.
this
指针隐式放置在堆栈上(就像方法的参数)。因此,当您调用时,obj->foo()
您会隐式地将 obj 传递给方法 foo。编译器允许您通过this
.
一般来说,无论如何都不需要将此指针存储在对象中。这将是多余的(即,如果您可以获取该对象,则其地址已经可供您使用)。
然而,vTable 是另一回事。在编译时无法知道对象指向哪个 vtable,也没有单独的隐式参数。这需要对象本身的专用空间。
无处。指针不是左值,因此this
不占用内存。这有点像询问结果的
x + y
驻留位置(wherex
和y
are int
)。根据实现,它实际驻留的位置会有所不同:例如,VC++ 倾向于将其保存在寄存器 ECX 中(尽管在使用优化时这可能会有所不同);Sun CC for Sparc 将其放入寄存器i0
等。它不是该类的成员,甚至是隐含的。最好将其视为函数的参数,尽管许多编译器会对其进行特殊处理,并且与普通参数不同,它不是左值。