在C语言的结构体概念中,为了计算出结构体的内存大小,我们了解到了内存对齐。在学习到C++的类与对象时,我们又遇到了一个问题:如何计算类对象的大小。
首先我们要知道什么是内存对齐
在C语言中,先来看一个例子:
typedef struct
{
int a;
short b;
double c;
}A;
typedef struct
{
int a;
double b;
short c;
}B;
分别求出sizeof(A),sizeof(B),得到的结果如下:
明明这两个结构体中的成员类型是一样的,只是先后顺序不同,为什么它们所占的内存大小就产生了差别呢?
这就引出了结构体的内存对齐:
在结构体中,从结构体的首地址开始,假设地址从0开始。
对结构体A来说,a是int类型占4个字节(从0~3),b是short类型占2个字节(从4~5),c占8个字节(从8~15)。
对结构体B来说,a是int类型占4个字节(从0~3),b是double类型占8个字节(从8~15),c占2个字节(从16~17)。
结构体的内存对齐规则:
对齐规则是按照成员的声明顺序,依次安排内存,其偏移量为成员大小的整数倍,0看做任何成员的整数倍。
最后结构体的大小为最大成员的整数倍 (所以这里的B中,最后结构体大小为double的倍数是24,而不是18)。
另:C语言中,空的结构体在内存中所占大小为0。(仅在gcc中测试为0)。
C++中计算类对象的大小
首先我们要知道类与对象的关系:对象是类的实例化。类是模型不占空间,实例化的对象才占空间。
在对象中,一个类的大小实际就是该类中“成员变量”之和。当然在求和时也要进行内存对齐。
sizeof计算类的大小时,只计算(非static的)数据成员变量即可,不用考虑那些成员函数。
举个例子:
这个类中既有成员变量,又有成员函数,但是在求类的大小时,只需将类中的成员变量相加,再进行内存对齐即可。
还有一种特殊情况:空类。
顾名思义,空类就是类中什么也没有。
class Y
{
};
基于上面提到的概念,我们可能会觉得空类中没有成员变量,所以它的大小就是0,我们测试一下:
可以看出空类的内存所占大小为1字节而非0,这是因为c++中,规定任何不同的对象不能拥有相同的内存地址。
也就是说,如果空类不占大小的话,那么同一类定义出多个对象后就会无法分辨出地址,且在C++中规定了任何不同的对象不能拥有相同的内存地址,所以编译器给了空类一个字节来唯一标识这个类。
所以空类的内存所占大小为1字节。
内存对齐的原因
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特
定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次
内存访问;而对齐的内存访问仅需要一次访问。