【问题标题】:understanding exactly how an object is mapped in memory [duplicate]准确了解对象在内存中的映射方式[重复]
【发布时间】:2019-03-13 19:12:50
【问题描述】:

我阅读了this question 和其他一些关于对象布局的内容,但我仍然不知道它的外观。

这是我的具体问题:

对于每个类(意味着如果我有 2 个超类,我将有 2 个指针),虚函数有 1 个vtable pointer。它在对象内部的什么位置?假设如下:class A{void virtual f(){}; int x;}; 对象A a 的地址是否与a.xa.f 的地址相同[或者可能指向默认方法,例如@987654329 @ 不正确,因为类方法未存储在对象中,如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 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;
}

【问题讨论】:

  • @DanielLangr 是的,我编辑了我的 Q 并附上了一个答案的链接。忘了也删​​掉那句话。
  • @1201ProgramAlarm 确实是类似,但是那里的答案有些不清楚
  • @CIsForCookies: "从下面假设 vtable 指针总是在其他类成员之前是否正确?" 你甚至不能假设 vtables 是 存在在 C++ 实现中。当然,大多数编译器确实使用它们作为实现虚函数的手段。但不能保证这一点。
  • int *p = (int*)&amp;a; 如果A 具有虚函数,我猜这是未定义的行为。您只能为 standard-layout classes 执行此操作。
  • @NicolBolas 所以基本上,在具有虚拟方法的类中,试图根据对象地址和偏移量查找特定成员注定要依赖于 UB 或至少依赖于实现?

标签: c++ vtable


【解决方案1】:

这完全依赖于实现(编译器),并且大多数实现倾向于将 vptr 作为第一个元素插入。由于它是对象地址的第一个元素和开头,因此虚拟函数调用的间接调用将更容易,因为没有进一步的偏移计算来识别 vptr。之前在 stackoverflow 中问过类似的问题,发现下面的问题很有用。 Why is vptr stored as the first entry in the memory of a class with virtual functions?

【讨论】:

  • 这个依赖于实现的变化有多大?我的意思是,正如我所看到的,它应该(意思是,我会这样做;-))位于对象的头部/尾部。实现它是否“合法”,例如,像非虚拟方法一样,即在代码段中或像这样疯狂的东西中,或者有一些指导方针?
  • 标准委员会可能已经定义了一些指南,将很快提供链接。
  • 这是《Inside C++ Object Model》一书的节选。
  • 斯坦利 B 李普曼。 “在 2.0 版之后,随着对多重继承和抽象基类的支持的增加,以及 OO 范式的普遍普及,一些实现开始将 vptr 放在类对象的开头。”
猜你喜欢
  • 1970-01-01
  • 2019-09-19
  • 2019-04-26
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
相关资源
最近更新 更多