C++类的空间分配
代码如下:
1 #include<iostream> 2 using namespace std; 3 4 class A 5 { 6 //char a; 7 }; 8 class B:public virtual A 9 {}; 10 class C:public virtual A 11 {}; 12 class D:public B,public C 13 {}; 14 int main() 15 { 16 cout<<"sizeof(A)="<<sizeof(A)<<endl; 17 cout<<"sizeof(B)="<<sizeof(B)<<endl; 18 cout<<"sizeof(C)="<<sizeof(C)<<endl; 19 cout<<"sizeof(D)="<<sizeof(D)<<endl; 20 return 0; 21 }
运行结果:
我的编译器是vs2012
class A不含任何成员时:
class A含有一个成员变量char a时:
不同的机器及不同的编译器下结果很可能是不一样的。
首先说一下他们的大小受那些因素的影响:
1.C++语言本身
当涉及到虚继承时,C++是通过某种形式的指针来实现的。比如说多态的实现就是通过查找虚函数表找到相应函数来实现的。
2.编译器优化
3.内存对齐
将数值调整到某数的整数倍,以使bus的"运输量"达到最高效率。
现在来看我们的问题:
1、为什么A的大小为1?
设想一下你写了这么句代码A temp;如果A的大小为0的话,操作系统要如何为temp分配内存呢?不分配内存的话如何去找到temp在哪呢?所以为了让类的对象在内存里有一个独一无二的地址,编译器会向空类里插入1byte 的char。sizeof(A)就为1喽。
2、B和C的大小
由于是虚继承,B和C会包含一个指针,有4byte。加上从A继承的1byte,应该是5byte啊。这里就涉及到上述的第二个原因了,编译器优化。由于B和C已经是4byte了,那么不存在问题1中的问题了,那么这时候编译器就没有去加上A中的1byte。如果你的测试结果是5,那说明你的编译器没有做这个优化。
如果你的结果是8,又是怎么回事呢,这就又涉及到上述第三点原因了,所谓内存对齐,就是说将数值调整到某数的整数倍,以使bus的"运输量"达到最高效率。32位机器上,这个‘某数’通常为4,所以5个字节的大小就被调整成了4的2倍 = 8。
3、D的大小
看第二幅图中,B=5,C=5,为什么D的大小不是5+5=10呢?
因为一个virtual base class subobject只会在 derived class中存在一份实体,不管它在class继承体系中出现了多少次。所以A的大小是1(A的大小)+4(B中除去A部分的大小)+4(C中除去A部分的大小) = 9。