C++ 内存对齐

内存对齐 #pragma pack()用法

什么是对齐 : 现代计算机中内存空间是按照byte划分,对类型的访问不能从任意位置开始, 访问特定变量要在特定内存地址访问,需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
.
然而不同硬件平台上对储存空间处理不同, 有些平台特定类型只能在特定地址上开始存取, 有些则是偶地址开始存放, 如果是偶数只需一次读出, 奇数则要两次,而且还要对高低位字节进行拼凑, 造成了效率损失.

在sizeof计算结构体的时候不是直接把里面的变量大小相加,而是要考虑内存对齐.在我们编写的时候往往编译器会自动帮我们选择适合的对齐方式,我们也可以通过#pragma pack()来指定对齐方式

结构体对齐规则
对齐模数 MIN (数据所占用内存 , #pragma pack()的值 )

#pragma pack(4)
struct Test1
{
	char c;
	short sh;
	int a;
	float f;
	int *p;
	char *s;
	double d;
};

在32位下,上面结构体28Bytes
c = 1bytes,放第一个位置[0]
sh = 2bytes , 2 < #pragma pack(4) 那么就放2的偶数倍,因为[0]被占用了那么只能放[2,3]
a = 4bytes , 4 == 4, 放在[4,7]
f = 4bytes 4 == 4 , 放[8,11]
*p , *s都是4bytes 则是[12,15] , [16,19]
d = 8bytes, 8 > 4 取4 , [20,27]
因为是28个bytes是4整数倍所以不需要补齐, 那么上面结构体就是28个bytes

struct Test2
{
	char c;
	double d;
	int a;
	short sh;
	float f;
	int *p;
	char *s;		
};

同理 c : [0] , d : [4,11] , a[12,15] , sh[16,17] , f[20,23] , p[24,27] , s[28,31]
变成了32个bytes

静态变量时存在静态数据区的,所以不占上面内存
空类占1个byte,因为c++要求每个实例内存独一无二
类内普通变量和struct对齐一样, 静态不纳入内存占用
类内普通方法不占内存
虚函数占4个bytes用来指定虚函数的虚拟函数表的入口地址, 和虚函数数量多少无关

//不包含虚函数时,对于类中的成员变量按结构体对齐方式处理
//普通函数函数不占内存。sizeof(CBase1)=8
#pragma pack(4)
class CBase1
{
private:
	char c;
	short sh;
	int a;
public:
	void fOut(){ cout << "hello" << endl; }
};
----------------------------------------------------------------
//包含虚函数
//包含虚函数时,类中需要保存虚函数表的入口地址指针,即需要多保存一个指针。
//这个值跟虚函数的个数多少没有关系。sizeof(CBase2)=12
#pragma pack(4)
class CBase2
{
private:
	char c;
	short sh;
	int a;
public:
	virtual void fOut(){ cout << "hello" << endl; }
};

子类所占内存大小是父类+自身成员变量的值。特别注意的是,子类与父类共享同一个虚函数指针,因此当子类新声明一个虚函数时,不必在对其保存虚函数表指针入口。

//sizeof(cDerive)= sizeof(cBase)+sizeof(int n) = 16
#pragma pack(4)
class CBase
{
private:
	char c;
	short sh;
	int a;
public:
	virtual void fOut(){ cout << "virtual 1" << endl; }
};
class cDerive :public CBase
{
private :
	int n;
public:
	virtual void fPut(){ cout << "virtual 2"; }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值