【问题标题】:Size of classes with virtual functions GCC/Xcode具有虚函数 GCC/Xcode 的类的大小
【发布时间】:2011-10-16 02:08:21
【问题描述】:

谁能向我解释这里发生了什么?首先,我认为大多数程序员都知道带有虚函数的类有一个 vtbl,因此在它的顶部有 4 个额外的字节。据我所知,这是相当标准的。我已经对此进行了测试并利用了这一事实,之前从带有补丁的 vtbls 的二进制文件中加载到位。在过去的 6 个月里,我一直在 Xcode 中工作,最近才发现需要做一些就地加载的东西,所以我正在考虑再次修补 vtbls。为了确保我的理解是正确的,我编写了一个示例程序。这里是:

class A
{
    public:
    virtual int getData()
    {
        return a;
    }

    virtual void print()
    {
        printf("hello\n");
    }
    int a;
};

class B : public A
{
public:
    int getData()
    {
        return b;
    }
    int b;
};

class C : public B
{
public:
    int getData()
    {
        return c;
    }

    void print()
    {
        printf("world\n");
    }
    int c;
 };

class D
{
public:
    int a;
    int b;
};

int main (int argc, const char * argv[])
{
    A* tA = new A();
    tA->a = 1;

    printf("A: %d\n", sizeof(A));
    printf("A data: %d\n", tA->getData());

    B* tB = new B();
    tB->a = 2;
    tB->b = 4;

    printf("B: %d\n", sizeof(B));
    printf("B data: %d\n", tB->getData());

    C* tC = new C();
    tC->c = 8;

    printf("C: %d\n", sizeof(C));
    printf("C data: %d\n", tC->getData());

    A* aC = tC;
    aC->print();

    printf("D: %d\n", sizeof(D));

    return 0;
}

我的预期输出是:

答:8

数据:1

B:12

B 数据:4

C:16

C 数据:8

世界

D:8

但是,我得到的输出是:

答:16

数据:1

B:16

B 数据:4

C:24

C 数据:8

世界

D:8

有人知道这里发生了什么吗?谢谢!

【问题讨论】:

  • 是的,我是——所以 vtbl 占用 64 位?
  • 虚拟表是一个指针。所有指针占用 8 个字节。
  • @alk3ovation,是的,当然(一个指针,呵呵)加上对齐问题,你得到 16 个字节。
  • 你想要的是多态序列化,试试google吧
  • 是的,我查阅了几篇关于多态序列化的文章,只是想确保我理解问题的所有部分。我什至没有想到我在 64 位机器上。并且对齐对于 8 字节指针是有意义的。好的,谢谢大家!

标签: c++ inheritance virtual sizeof


【解决方案1】:

类 A 到 C 的实例包含一个 vptr,一个指向动态类型的虚函数表的指针。该指针在 64 位机器上占用 8 个字节(或在 32 位机器上占用 4 个字节)。每个 int 成员占用 4 个字节。

sizeof(Class)的最小值是所有成员的sizeof(member)之和。如果是这样的话,那么

sizeof(A) = 8 (vptr) + 4 (int a) = 12
sizeof(B) = 8 (vptr) + 4 (int a) + 4 (int b) = 16
sizeof(C) = 8 (vptr) + 4 (int a) + 4 (int b) + 4 (int c) = 20
sizeof(D) = 4 (int a) + 4 (int b) = 8

但是,这只是最小大小。编译器通常将此大小增加到 sizeof(void*) 的倍数,这里是 8 个字节。这个过程称为对齐。看起来这会浪费内存,但性能提升超过了这一点:CPU 读取对齐数据的速度比非对齐数据快得多。

顺便说一句,如果您使用的是 32 位机器,您的预期结果应该是正确的。指针(尤其是 vptr)在那里有 4 个字节宽,并且对齐也是 4 个字节的倍数。由于相关类的所有数据成员都是 4 字节大,因此对齐不会在那里做任何事情。

【讨论】:

    猜你喜欢
    • 2014-04-02
    • 2020-10-31
    • 2011-09-16
    • 2021-10-17
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多