C++中:类数据成员的内存布局

来源:互联网 发布:啊哈算法pdf百度云 编辑:程序博客网 时间:2024/05/24 07:11

首先我们从一个有趣的问题引入:  

class A  { };

当我们运行 :cout<<"sizeof(A)"<<endl;会惊奇的发现,j结果不是0,而是1;

为啥会是这样呢?其实在《深度探索C++对象模型》一本书中,有详细的解读,我在这只想说说自己的理解:首先class A 是一个类型,是用来实例化对象的,所以它就必须有具体的空间,使系统能按照它的格式分配内存。

如果  A   a; 当然sizeof(a)的结果也是1。这个是因为它是以一个对象存在的,我们必有有一个空间(地址)能够让我们的程序找到它。

所以让我们再返回书中描述,在这种情况下,编译器为我们自动插入一个 char 以满足能够占用内存的效果。

class A{   int   a;  char  c;  };

class B :public virtual  A { };

class C :public virtual A { };

class D:public  B ,public  C { };

下面是调试代码:

#include<iostream>using namespace std;class A{        int   a;               char  c; };class B :public virtual  A { };class C :public virtual A { };class D:public  B ,public  C { }; int main(void){cout<<sizeof(A)<<endl;cout<<sizeof(B)<<endl;cout<<sizeof(C)<<endl;cout<<sizeof(D)<<endl;return 0; }

上面结果 :  8   12   12   16    

C++在类的数据成员布局上有几个因素:

1: 语言本身所造成的负担。

   当语言支持virtual base class 时,就会产生一些类似vptr的额外指针,会是类的内存空间扩大。上面的例子就是 B  C 没有添加任何数据成员,只是virtual的继承了A,他们的内存就扩大了4 (一个指针的容量)。理解这块,可以和vptr 联系起来,类似。

2:Alignment (内存对对齐)。 

这个类似于C语言中struct中的内存对齐,及异质数据组合,编译器会为了CUP读去数据的效率而做一些优化。即 字节对齐。

有关内存对齐的问题可以参考这篇文 :

http://blog.csdn.net/trageday_motata/article/details/20637509

由于内存对齐的原因,A的值为8. 在继承过程中,派生类的大小是在基类的基础上增加自己添加的空间,B 和C添加了一个类似vptr的指针,所以是12.

那么,D为啥是16呢,按照添加的原理,不是应该是12+12=24 为啥是16呢,这就是c++中虚继承的缘故,虚继承就是为这种,多重派生类中可能会存在多个基类的副本而提出的。即12+12-8=16 减去一个A的副本就是本来D的空间大小。

另外,我们如果把calss  A  改一下:

class A{        int   a;       char  c;       virtual void fun()=0; };
这是的结果会是:12 ,因为有了虚函数,编译器就会为每一个类的对象分配一个vptr,用来指向自己的虚函数表 virtual  table





0 0