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

understanding exactly how an object is mapped in memory

我阅读了 this question 和其他一些关于 on object 布局的内容,但我仍然不明白它到底是什么样子。

这是我的具体问题:

对于每个 class(意味着如果我有 2 个超级classed 我将有 2 个指针),虚函数有 1 vtable pointer 给他们。它在对象内部的什么位置?假设如下:class A{void virtual f(){}; int x;}; 对象 A a 的地址是否与 a.xa.f [ 的地址相同或者可能指向默认方法,例如 C-tor / D-tor Incorrect,因为 class 方法未存储在对象内部正如所解释的 here]

示例:

    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)的虚函数时,会在对象中添加一个指针(4字节,在我的32位机器上)。它会被添加到其他数据成员之前吗?

指向什么:

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

我用这个检查了一下。从以下假设 vtable 指针总是先于其他 class 成员是否正确?:

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。之前在Whosebug上问过类似的问题,发现下面这个很有用。