C++中的内存对齐

内存对齐

内存对齐

为何要有内存对齐?

  • 1、可移植性。有些CPU可以访问任意地址上的任意数据,而有些CPU只能在特定的地址上访问,如果在编译的时候将分配的内存对齐,这样就具有平台的可移植性。
  • 2、提升性能。CPU每次寻址都需要花费时间,且访问是按照字长为单位来到,而且如果访问为对齐的内存,处理器需要做两次内存访问,比如CPU某个字的时候,数据从第二个字节开始存储,只存储了一部分,CPU还需要访问下一个字来得到剩下的数据。

类对象的对齐规则

  • 首先不同平台不同编译器有不同的对齐系数,默认的对齐系数一般是4个字节。
//显示对齐系数
#pragma pack(show) 

image-20230914173459708

//修改对齐系数
#include <iostream>
#pragma pack(4) 
#pragma pack(show) 

using namespace std;
int main(){
}

image-20230914173614385

  • 在类中,第一个成员位于偏移量为0的位置,当然如果有虚函数,0的地方就会是虚函数指针,这就是另外的情况了,从0往后,每个成员的首地址都必须是自身大小和默认对齐系数中比较小的那一个的整数倍,编译器会在中间空余的地方填充字节,一般是填充0。举个例子设置一个类,里面包含3个bool类型的变量和一个int类型的变量,bool类型的大小为1个字节,所以每个bool变量的首地址都要是1的倍数,也就是地址0-1是bool A,1-2是bool B,2-3是bool C,然后是int变量了,由于它的对齐数应该为4,所以它的内存空间应该是地址4-8,而地址3-4则会被系统填充为0。所以一个这样的类的对象大小为8个字节,中间有一个字节填充用于字节对齐。
class A {
public:
	bool b = true;
	int a = 1;
};
int main(){
	cout << sizeof(A) << endl;
}

输出结果:

8
  • 而对于整个类来说,最后整个类的地址必须是 默认对齐系数和类中最大的类型大小 中比较小的那一个。比如一个int 一个bool,类自身只有5个字节,但是整个类的地址必须是 默认对齐系数和类中最大的类型大小 中比较小的那一个,也就是4,所以对齐为8字节。
class A {
public:
	int a = 1;
	bool b = true;
};
int main(){
	cout << sizeof(A) << endl;
}
  • 另外变量内存对齐分布是跟顺序有关的,同样是3个bool和一个int,若干先声明两个bool在声明一个int最后声明一个bool,此时两个bool分布在0-2,3-4填充,int分布在4-8,而最后的bool又要放在9上,因此最后类的大小就变成了9,同时又因为类也要对齐为4的倍数,说如果用sizeof查看这个类的大小会是12个字节。
class A {
public:
	bool c = false;
	int a = 1;
	bool b = true;
};
class B {
public:
	bool c = false;
	bool b = true;
	int a = 1;
};
int main()
{
	cout << "sizeof(A):" << sizeof(A) << endl;
	cout << "sizeof(B):" << sizeof(B) << endl;
}

输出结果:

sizeof(A):12
sizeof(B):8
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值