c++内存对齐--GeekBand

2016-06-06  本文已影响106人  数据小冰

c++中每个class包含两部分:数据和函数。对每个对象来说函数部分大家公用一份,而数据部分每个对象是独立的。所以在求一个class所占的空间大小的时候,求得数据部分所占的内存大小即为class的大小。下面小将结合实验的方式测试验证,考虑到vs下编译器和gcc的不同,小编这里分别独立验证,vs编译器验证采用vs2013IDE,gcc下的验证用codeblocks,测试都是在32系统下。class Fruit{
int no;
double weight;
char key;public:
void print() { }
virtual void process(){ }
};
所以这里的Fruit类,no是int型,占4个字节(实验是在32系统下,下面也是),weight是double型占8个字节,key是字符型占1个字节,别忘了这里有个虚函数,有一个隐藏的虚函数指针占4个字节。所以4+8+1+4=17个字节。
真是这么多吗,用sizeof测试下就知道了,在vs2013下sizeof(Fruit)==32.具体是怎么分配的呢?实验验证如下:

1.png

可以看到,指向虚函数的指针所占位置是从偏移量0位置开始的,占用8个字节。no变量从偏移量8位置开始,占用4个字节,但为了对齐,这里又分配了4个字节(alignment member)(size=4)。weight从偏移量16开始,占用8个字节。key从偏移量24开始,占用一个字节,但这里为了对齐,又分配了7个字节。所以共占用8+4+4(对齐)+8+1+7(对齐)=32字节。

vs2013下Fruit类和Apple类占用内存大小
有继承的情况占用的内存情况又是什么样的呢?比如下面的代码,Apple所占用的空间是多少呢?
class Apple : public Fruit{
int size;
char type;
public:
void save() { }
virtual void process(){ }
};
vs2013下实际测试sizeof(Apple)==40,具体是怎么分配的,验证结果如下

2.png

可以看到,Apple继承了Fruit数据,Furit部分所占用的空间是32字节,Apple类本身的size占4个字节,type 是占1个字节,但为了对齐多占了3个字节。

codeblocks(gcc)下Fruit类和Apple所占内存大小
同样是上面的Furit类和Apple,通过下面的代码测试

int main()
{
cout<<sizeof(Fruit)<<endl;
cout<<sizeof(Apple)<<endl;
return 0;
}
测试结果为:

codeblocks内存.png

哪在gcc下为什么Fruit类为什么是24字节呢?
虚函数指针(4字节)+no(4字节)+weight(8字节)+key(1字节,为了对齐添加了7字节)=24字节
哪gcc下Apple类是32字节是怎么来的呢?
虚函数指针(4字节)+no(4字节)+weight(8字节)+key(1字节,为了对齐添加了3字节)+size(4字节)+type(1字节,为了对齐添加了7字节)=32字节

为什么vs2013下和codeblocks下Fruit类和Apple类所占用的空间不同呢?
这是因为vs2013是微软的vc编译器,codeblocks是gcc编译器。两者在对齐的时候采用的策略不同。vs2013下采用的是以最大变量所占用的字节为标准,即以double型的weight为标准,所以Fruit类中int型的no不足8字节都会补足到8字节,所以no补了4字节。char型的key补了7字节。在Apple类中最大变量是int型的size,所以type补了3字节。
gcc就不是以这样的标准,gcc对齐重点两点,
1)变量的偏移位置是该变量所占内存的整数倍,如果不满足则补齐,size不满足,所以key补了3字节
2)所有变量占的字节数是最大变量所占字节的整数倍,如果不满足则补齐,所有type补了7字节。

上一篇下一篇

猜你喜欢

热点阅读