sizeof——类和结构体

来源:互联网 发布:开农村淘宝怎么赚佣金 编辑:程序博客网 时间:2024/05/17 01:41

一个类的大小和数据成员有很大的关系,总结下sizeof(类)的各种情况

首先看一个空类的大小:

class A{};int main(){cout<<sizeof(A)<<endl;//输出结果1return 0;}

类中没有任何成员变量,sizeof(A)的结果是1,书上说编译器插入了一个char,使得这个class的不同实体在内存中配置独一无二的地址。

在类中添加构造和析构函数,看起来类中添加了函数,大小会不会变化呢?

class A{public:A();~A();};int main(){cout<<sizeof(A)<<endl;//输出还是1return 0;}

结果还是1,就是说类的析构函数没有存放在类的对象空间,其实不管是全局函数还是成员函数,都是存放在代码区,所以不占类的空间,在类中定义成员函数或者在成员函数中定义变量,都不会影响类的大小。但是虚函数是通过一张虚函数表来来实现的,编译器要保证虚函数表的指针存在于对象实例中最前面的位置,这是为了正确取到虚函数的偏移量:

class A{virtual int fun(){};};int main(){cout<<sizeof(A)<<endl;  //输出4return 0;}


在类中定义变量又是如何影响大小的?

class A{int a;char b;char c;};class B{char b;int a;char c;};int main(){cout<<sizeof(A)<<endl;//输出8cout<<sizeof(B)<<endl;//输出12return 0;}

在32位编译器中,int占4个字节,char占一个字节,A中本来应该是占6个字节的,实际上为了空间和复杂度上的平衡采用了内存对齐,按照以下三个条件来计算大小:

1.结构体(类)的首地址能够被其最宽的基本类型成员大小所整除

2.每个成员相对于首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间填充字节

3.结构体的总大小为最宽的基本类型大小的整数倍,如有需要编译器会在最后一个成员之后加上填充字节


对于A的大小:

****|****     8字节

int(4) | char(1)char(1)+两字节填充      8字节

对于B的大小

****|****|****12字节

char(1)+3填充字节 | int(4) | char(1)+3填充字节    12字节

这就是相同成员变量占用不同内存大小的原因。下面在看一个例子:

class A{static int a;char c;char d;};int main(){cout<<sizeof(A)<<endl;//输出2return 0;}
由于静态变量在全局区存放,在类域中为所有对象共享,不属于任何对象,所以int a不占类大小。

有继承关系的类的大小:

class A{int a;char c;char d;};class B:A{char e;int b;};int main(){cout<<sizeof(A)<<endl;//输出8cout<<sizeof(B)<<endl;//输出16return 0;}

A根据上面所说的内存对齐大小为8,B也需要内存对齐,并且继承了A,所以大小为A+B = 16;