内存空间对齐

内存空间对其原则:

概念:自身对齐值与有效对齐值。
一般数据成员的自身对齐值为其自生占据的内存空间大小。结构体的自生对齐值为其内部最大数据成员的所占内存空间。
有效对齐值为自身对齐值与指定的对齐值相比的较小值。所以在一般的结构体中。有效的对齐值就是一般其成员变量的自身对齐值。

总的来说就是每一个成员存放位置相对于它的域起点偏移为有效的对齐值整数倍。
对齐因子如果不人为设定即为该成员变量的大小。
结构体存放的地址为有效对齐值的整数倍,且第一个成员的偏移为0.后面的成员。根据有效的对齐值进行偏移,一般是自生的大小。最后结构体的大小也必须是有效对齐值的整数倍。

内部结构体对齐原则:结构体存放起点地址为结构体内部的最大成员(自身对齐值)的整数倍,然后内部结构体也遵循结构体填补为最大成员的整数倍。外部的结构体也是存放起始地址为内部最大的存储变量的整数倍。

尾部对齐,整个结构体所占的内存空间应该是它内部的最大长度数据成员(有效对齐值)的整数倍。(其实是其有效对齐值的整数倍。一般情况下结构体的自身对齐值与有效对齐值是星等的。)

尾部对齐特别容易被忽略,必须是对齐因子的整数倍。

当有段标示符代码
pragma pack(n)时,对齐因子就是与n相比其中最小的一个。且pragma 影响从声明开始往下的类。
MSDN上指明开发n需要使用的是1,2,4,8或16其他非2的倍数值运算有误

所以第一条改为偏移位置为变量与n相比较小的整数倍位置。

关键的第二条,
结构体变量的起点位置满足外部对齐要求,即是取变量与小的作为对齐地址,但是在计算该内部结构体大小时,对齐只看自身有没有param pack的限制,如果没有,那么就按照常规的方法进行对齐。

第三条还是为n的整数倍对齐

实例练习:
1、
class C
{

char a;//0-3
double b;//8-15
int *c;//16-19 填充到24

};
Sizeof(cinstance) = 24运行结果无误

class BB
{
private:
int b;//0-3
double c;//8-15

};

class AA
{
private:
int a;//0-3;
double b;//8-15;
BB fg;//16-31
char*c;//32-35//填¬?充?到Ì?39
};

Sizeof(aa.instance) = 40;

class BB
{
private:
int b;//0-3
double c;//8-15

};

class AA
{
private:
int a;//0-3;
int b;//4-7;
BB fg;//8-23
char*c;//24-27//填¬?充?到Ì?39
};
Sizeof = 32;

注意最后的补零,还要考虑内部的结构体的变量具有最大的长度。如果是,那么以它为基准尾部对齐

含有pragma的情况
考虑内部还有结构体的情况

当类中存在函数时,对整个类占用的数据空间大小的影响

我们知道类中的函数对于对象而言都是在共有的,不同对象调用时通过传递this指针调用函数。间接的调用函数。

Pragma 的覆盖效果
每一句pragma的效果只从当前起点开始计算,也就是说,如果该类中有结构体变量,而结构体变量的定义在pragma的前段,那么这个结构体变量不会有任何影响。
并且一个结构体中的结构体变量只受到自身的pragma约束,其起始地址受到当前pragma的约束,但自己内部的成员对齐不会受到当前的pragma的约束。这个字段自身占用的大小受到其自身的限制,但是起始地址会受到外部类的pragma约束限制。
含有成员函数的情况

如果存在虚函数

类所占的空间 = 类成员变量所占空间 + 4(如果存在虚函数的话)(还要考虑补齐)。

如果成员函数中存在虚函数,则所有的虚函数保存在虚函数表中,然后类中会有一个指针指向该表;这个指针需要占用空间,所以需要 +4;

如果是空类,则空间为1。
因为在C++中每一个实例都有唯一的地址,因此空类占据的地址空间为1。
1个字节表示空类实例化且占用空间最少。

一个类能够实例化,编译器就需给它分配内存空间,来指示类实例的地址;这里编译器默认分配了一个字节(如:char),以便标记可能初始化的类实例,同时使空类占用的空间也最少(即1字节)”。

含有继承关系的时候计算类的大小
派生类的占用空间包含父类的存储空间+派生类的存储空间+4虚函数的指针占用空间
虚函数只占用4个字节;记住虚函数都是4个字节指针。就算派生类中具有虚函数也一样是只记四个字节。

但是还是具有对齐的问题,需要与最大的变量长度对齐。

如果父类中有虚函数。在派生类中不需要计算虚函数的存储空间,他们公用一块区域

所以派生类的存储空间为基类的存储空间+派生类非静态成员的空间。

更特殊的虚继承。

基类的存储空间+派生类的非静态成员变量+每一个派生类中的虚函数。

这个时候派生类的虚函数指针与基类的虚函数指针不一样,所以要叠加大小。叠加的大小要么为4要么为0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值