我们知道C++中不同类型数据占不同字节的,具体见下表:
数据类型 | 32位 | 64位 |
char | 1 | 1 |
int | 4 | 4 |
float | 4 | 8 |
double | 8 | 8 |
那么对于一个结构体或类占多少字节呢?
我们首先定义一个类:
class people
{
public:
int age_p;
double weight_p;
char name[5];
};
机灵的小伙伴可能一口说出这个类所占的字节为4(int)+8(double)+5(char)=17。结果真的是这样吗?我们先创建这个类的一个对象p2 再sizeof(p2)获得该对象所占内存。
people p2;
cout<<"p2内存大小:"<<sizeof(p2)<<endl;
结果为:
意外的是结果是24,那么到底是什么原因造成这样的结果呢?我们不妨将这个类中每个成员变量的地址与内存均显示出来,再进行分析。这里显示的地址为了直观性我选用了十进制地址显示的转换函数ip2decimal(),具体函数代码见:“C++显示十进制内存地址”。
people p2;
cout<<"p2地址:"<<ip2decimal(&p2)<<endl;
cout<<"p2内存大小:"<<sizeof(p2)<<endl;
cout<<"p2.age_p地址:"<<ip2decimal(&p2.age_p)<<endl;
cout<<"p2.age_p内存大小:"<<sizeof(p2.age_p)<<endl;
cout<<"p2.weight_p地址:"<<ip2decimal(&p2.weight_p)<<endl;
cout<<"p2.weight_p内存大小:"<<sizeof(p2.weight_p)<<endl;
cout<<"p2.name地址"<<ip2decimal(&p2.name)<<endl;
cout<<"p2.name内存大小"<<sizeof(p2.name)<<endl;
结果为:
由此可见虽然在person类中int型的age_p只需要4个字节,但系统给他分配了8个字节,double型分配了原本所需的8个字节,char虽需要5个字节但系统也给分配了8个字节,因此person实际的存储结构为:
由此可知系统在为类分配内存空间时,如果类中某个对象所需空间最多为2^x,那么类中其它类型成员变量都会按照2^x的标准被系统分配空间。
这种内存分配模式貌似会造成内存的浪费,实则不然,系统会根据不同对象的大小动态调节存储,我们再来看一个例子,首先定义一下它的类:
class data
{
public:
int num1;
int num2;
int num3;
char str1[4];
double num_double;
char str2[5];
};
data p;
它的类与成员变量的地址与内存大小分别为:
由此可知类data的存储结构为:
到这里我们可以得出结论:
对于一个类,系统会根据类中所需空间的最大的成员变量创建2^x大小的子空间,然后将类中成员变量依次往里放,当子空间满了或者子空间剩余空间无法放入下一个成员变量时,就会创建新的一个子空间,循环往复,直到所有的成员变量都放入到子空间中,最终的类的空间大小应该为子空间内存大小的整数倍。
对于结构体存储结构与类一致,感兴趣的可以自行实验。本文中如有表述错误的地方欢迎指正交流。