准确了解对象在内存中的映射方式

understanding exactly how an object is mapped in memory

本文关键字:映射方式 内存 了解 对象      更新时间:2023-10-16

我读了这个问题和其他一些关于对象布局的问题,但我仍然不明白它的外观。

这是我的具体问题:

对于每个类(这意味着如果我有一个 2 个超类,我将有 2 个指针(,虚函数对它们有 1 个vtable pointer。 它在对象内部的什么位置?假设以下内容:class A{void virtual f(){}; int x;};对象的地址A aa.xa.f的地址相同[或者可能指向默认方法,例如C-tor / D-tor不正确,因为类方法未存储在对象中,如此处所述]

例:

class A{
int x;
void f(){}
void virtual g(){}
void virtual h(){}
};
A a;
std::cout << sizeof a; // result = 8
class A{
int x;
void f(){}
void virtual g(){}
};
A a;
std::cout << sizeof a; // result = 8
class A{
int x;
void f(){}
//void virtual g(){}
};
A a;
std::cout << sizeof a; // result = 4

从这些例子可以看出,当遇到一个虚函数的数量(n> 0(时,一个指针(在我的 32 位机器上为 4 个字节(被添加到对象中。是否会将其添加到其他数据成员之前?

将指出什么:

A a;
int *p = (int*)&a;

我用这个检查了一下。从下面假设 vtable 指针总是在其他类成员之前是否正确?

class A{
public:
A(int y){x=y;}
virtual void g(){}
int x;
virtual void f(){}
};
int main ()
{
A a(42);
int *p = (int*)&a;
std::cout << *p << std::endl;      // = 4215116 (vtable address?)
std::cout << *(p+1) << std::endl;  // = 42
return 0;
}

这完全依赖于实现(编译器(,大多数实现倾向于插入 vptr 作为第一个元素。由于它是对象地址的第一个元素和开头,因此虚拟函数调用调用的间接寻址将更容易,因为没有进一步的偏移量计算来标识 vptr。之前在stackoverflow中提出类似的问题,发现下面的问题很有用。 为什么 vptr 作为具有虚函数的类的内存中的第一个条目存储?