C ++对象内存布局

时间:2014-02-09 19:58:09

标签: c++ object-layout

我试图理解多重继承中C ++的对象布局。 为此,我有两个超类A,B和一个子类C. 尝试转储它时我期望看到的是: vfptr | A |的领域vfptr | B |的领域C.的领域。

我得到这个模型,但有一些我不明白的零。 这是我正在尝试的代码

    #include <iostream>

    using namespace std;

    class A{
       public:
       int a;
       A(){ a = 5; }
       virtual void foo(){ }
    }; 

    class B{
       public:
       int b;    
       B(){ b = 10; }
       virtual void foo2(){ }
    };

    class C : public A, public B{
       public:
       int c;    
       C(){ c = 15; a = 20;}
       virtual void foo2(){ cout << "Heeello!\n";}
    };

   int main()
  {
    C c;
    int *ptr;

ptr = (int *)&c;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;
ptr++;
cout << *ptr << endl;

       return 0;
   }

这是我得到的输出:

4198384     //vfptr
0
20          // value of a
0
4198416     //vfptr
0
10          // value of b
15          // value of c

中间零的含义是什么? 提前谢谢!

6 个答案:

答案 0 :(得分:2)

这取决于你的编译器。有了clang-500,我得到了:

191787296
1
20
0
191787328
1
10
15
1785512560

我确信这也有一种GDB方式,但如果我在类对象的地址处将LLDB的指针大小的字转储出来,这就是我得到的结果:

0x7fff5fbff9d0: 0x0000000100002120 vtable for C + 16
0x7fff5fbff9d8: 0x0000000000000014
0x7fff5fbff9e0: 0x0000000100002140 vtable for C + 48
0x7fff5fbff9e8: 0x0000000f0000000a

这种布局似乎很明智,对吧?正是你所期待的。 在程序中没有像在调试器中那样显示干净的原因是你要转储int大小的单词。在64位系统sizeof(int)== 4但sizeof(void *)== 8

因此,您会看到指针分为(int,int)对。在Linux上,你的指针没有任何位设置超过低32,在我的指针OSX上 - 因此0和1差异的原因

答案 1 :(得分:2)

这非常依赖于体系结构和编译器...可能对你来说,指针的大小可能不是int的大小......你使用什么架构/编译器?

答案 2 :(得分:2)

如果您正在使用64位系统,那么:

  • 第一个零是第一个vfptr中最重要的4个字节。

  • 第二个零是填充,因此第二个vfptr将与8字节地址对齐。

  • 第三个零是第二个vfptr中最重要的4个字节。

您可以检查是否sizeof(void*) == 8以断言。

答案 3 :(得分:1)

很难说不知道你的平台和编译器,但这可能是一个对齐问题。实际上,编译器可能会尝试沿8字节边界对齐类数据,并将零用于填充。

如果没有上述细节,这只是推测。

答案 4 :(得分:1)

这完全取决于您的编译器,系统,位数。

虚拟表指针将具有指针的大小。这取决于您是将文件编译为32位还是64位。指针也将在其大小的多个地址处对齐(通常是任何类型)。这可能是您在20之后看到0填充的原因。

整数将在特定系统上具有整数的大小。这通常是32位。请注意,如果您的计算机不是这种情况,您将得到意外的结果,因为您使用指针算法将size(int)增加了ptr。

答案 5 :(得分:1)

如果您使用MVSC,您可以使用-d1reportAllClassLayout转储解决方案中所有类的所有内存布局:

cl -d1reportAllClassLayout main.cpp

希望对你有所帮助