Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;对象内存布局 我试图理解C++在多继承中的对象布局。 为此,我有两个超类A、B和一个子类C。 当我尝试倾倒它时,我期望看到的是: vfptr | A的字段| vfptr | B的字段| C的字段_C++_Object Layout - Fatal编程技术网

C++;对象内存布局 我试图理解C++在多继承中的对象布局。 为此,我有两个超类A、B和一个子类C。 当我尝试倾倒它时,我期望看到的是: vfptr | A的字段| vfptr | B的字段| C的字段

C++;对象内存布局 我试图理解C++在多继承中的对象布局。 为此,我有两个超类A、B和一个子类C。 当我尝试倾倒它时,我期望看到的是: vfptr | A的字段| vfptr | B的字段| C的字段,c++,object-layout,C++,Object Layout,我得到了这个模型,但是有一些我不明白的零。 这是我正在尝试的代码 #include <iostream> using namespace std; class A{ public: int a; A(){ a = 5; } virtual void foo(){ } }; class B{ public: int b; B(){ b

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

    #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;
   }
中间的零是什么意思?
提前谢谢

在不了解平台和编译器的情况下很难判断,但这可能是一个对齐问题。实际上,编译器可能会尝试沿8字节边界对齐类数据,并使用零作为填充


没有上面的细节,这只是猜测。

这取决于您的编译器。使用叮当-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上,您的指针没有任何位设置超过low 32,而在OSX上,我的指针是这样设置的-因此,0与1之间存在差异的原因是这在很大程度上取决于体系结构和编译器。。。对于您来说,指针的大小可能不是整数的大小。。。您使用的是什么体系结构/编译器?

如果您使用的是64位系统,那么:

  • 第一个零是第一个
    vfptr
    的4个最高有效字节

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

  • 第三个零是第二个
    vfptr
    的4个最高有效字节


您可以检查sizeof(void*)==8,以断言这一点。

这完全取决于您的编译器、系统和比特数

虚拟表指针的大小将与指针相同。这取决于您是将文件编译为32位还是64位。指针也将在其大小的多个地址上对齐(就像任何类型的指针一样)。这可能就是为什么在
20
之后出现0填充


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

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

cl-d1reportAllClassLayout main.cpp


希望它对您有所帮助

编译器:g++(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3。据我所知,0被用作一种分隔符?@Griwes:你是在LLVM svn上还是在发布的clang上?没有“C++的对象布局”之类的东西。有一个“你的编译器本周碰巧在你的平台上生成的对象布局”。
中间的零是什么意思?提前谢谢对齐填充。这是编译器特有的@n、 最好是上周和下周相同的编译器为这个平台生成相同的布局。如果您希望编译器之间的交互最少,那么最好使用不同编译器为同一平台生成的相同布局。这取决于架构和平台,您应该将它们添加到问题中。例如,英特尔的windows/64和linux/32的布局将非常不同,并且很可能与Solaris中的sparc/64不同…@DavidRodríguez dribeas这确实很好,但这类布局无法保证。我刚刚检查过。。谢谢!
0x7fff5fbff9d0: 0x0000000100002120 vtable for C + 16
0x7fff5fbff9d8: 0x0000000000000014
0x7fff5fbff9e0: 0x0000000100002140 vtable for C + 48
0x7fff5fbff9e8: 0x0000000f0000000a