C++的结构体和类是如何进行字节对齐的?

由于,C/C++中结构体和类的内存模型基本上是一样的,所以我们这里只讨论类是怎么样的。结构体也是采用相统的原则

我们都知道,在类中,如果我们用sizeof()去查看它的大小会返回这个类的所占的字节大小,但是这个大小并不是直接叠加的。比如我们知道:
一个 int 类型占用4字节,一个char类型占用一个字节,可是他们两个放在同一个类中,他们的大小并不是 4+1=5字节。
而是8字节,这是因为编译器对存放在类中的这两个成员变量进行了补齐。
那么补齐的规则是什么?这里废话不多说,直接说结论:

C++ 中按照类中最大成员变量的字节数决定粒度,然后进行补齐。但是要注意,最大粒度就到8字节

**

这个机制叫做译注(alignment): alignment:就是将数值调整到某数的倍数,在32位计算机上,通常alignment位4bytes(32位) ,以此来使得bus的传输效率最大

**

举几个例子说明:

在这里插入图片描述
在这里,对于class A来说,它的最大成员变量也就是a,字节数是8,所以编译器会决定存取class A中成员变量的时候会用8字节作为粒度,对于字节数仅仅位1的b,也会补齐位8字节。所以一共占用16字节。

在这里插入图片描述这个例子中,我们一直 string类的字节数占用40字节,b占用一个字节,编译器会以str作为最大粒度,可是最大粒度只有8字节(我想这应该是因为64位机器的存取最大粒度就到8字节,比如对于存器粒度最大位128字节的GPU来说,可能就不是这样)
因此编译器按照8字节的粒度,58+8=48
在这里插入图片描述在这个例子中,我们知道str占用2字节,b占用3字节。可是char的粒度是1字节,而short的粒度是2字节,所以它依然会按照粒度位2来做补齐。b会被以2
2进行填充,最终结果就是2*2+2=6

在这里插入图片描述在这个例子中,class A最大成员变量的粒度是4字节,但是m_x,m_z的大小,刚好可以达到一个4字节的粒度。
所以它们加起来,4*2+4=12

**

关于字节对齐的底层原理:

**
进行补齐的根本原因是因为CPU存取效率的因素,CPU理论上是可以访问内存中的所有地址。
可是对数据的存取并不是按照一个字节一个字节来进行的,而是一次4个字节或一次8个字节,因为这样可以一次存取多个字节,带宽比较高,对于GPU这种需要追求高带宽的计算设备来说,它的存取带宽可以达到128字节

假设我们的存取粒度是8字节,那么CPU在内存中寻址的起始地址,就必须是8的倍数,也就是0,8,16…
如果我们不进行字节对齐。就有可能出现这种情况,假设我有一个8字节的数据a,如果a的其实地址是0,那么CPU只需要一次就能对它进行存取,如果它的起始地址是1~7,那么CPU就需要两次才能对它进行存取。
所以字节对齐,是为了要提高效率。

因此C++会将比较小的数据进行填充,占用需要的空间,一次来达到对齐的目的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值