sizeof——类和结构体

本文探讨了C++中sizeof运算符用于计算类大小时的规则,包括空类、含有成员函数(包括虚函数)、数据成员的情况。文章详细解释了内存对齐、编译器如何在成员间插入填充字节以满足对齐要求,以及这种对齐方式如何影响具有相同成员但排列不同的类的大小。此外,还提到了继承关系对类大小的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个类的大小和数据成员有很大的关系,总结下sizeof(类)的各种情况

首先看一个空类的大小:

class A{};

int main(){
	cout<<sizeof(A)<<endl;//输出结果1
	return 0;
}

类中没有任何成员变量,sizeof(A)的结果是1,书上说编译器插入了一个char,使得这个class的不同实体在内存中配置独一无二的地址。

在类中添加构造和析构函数,看起来类中添加了函数,大小会不会变化呢?

class A{
	public:
	A();
	~A();
};

int main(){
	cout<<sizeof(A)<<endl;//输出还是1
	return 0;
}

结果还是1,就是说类的析构函数没有存放在类的对象空间,其实不管是全局函数还是成员函数,都是存放在代码区,所以不占类的空间,在类中定义成员函数或者在成员函数中定义变量,都不会影响类的大小。但是虚函数是通过一张虚函数表来来实现的,编译器要保证虚函数表的指针存在于对象实例中最前面的位置,这是为了正确取到虚函数的偏移量:

class A{	
	virtual int fun(){};
};

int main(){
	cout<<sizeof(A)<<endl;  //输出4
	return 0;
}


在类中定义变量又是如何影响大小的?

class A{
	int a;
	char b;
	char c;
};
class B{
	char b;
	int a;
	char c;
};

int main(){
	cout<<sizeof(A)<<endl;//输出8
	cout<<sizeof(B)<<endl;//输出12
	return 0;
}

在32位编译器中,int占4个字节,char占一个字节,A中本来应该是占6个字节的,实际上为了空间和复杂度上的平衡采用了内存对齐,按照以下三个条件来计算大小:

1. 结构体(类)的首地址能够被其最宽的基本类型成员大小所整除

2. 每个成员相对于首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间填充字节

3. 结构体的总大小为最宽的基本类型大小的整数倍,如有需要编译器会在最后一个成员之后加上填充字节


对于A的大小:

****|****     8字节

int(4) | char(1)char(1)+两字节填充      8字节

对于B的大小

****|****|**** 12字节

char(1)+3填充字节 | int(4) | char(1)+3填充字节    12字节

这就是相同成员变量占用不同内存大小的原因。下面在看一个例子:

class A{	
	static int a;
	char c;
	char d;
};


int main(){
	cout<<sizeof(A)<<endl;	//输出2
	return 0;
}
由于静态变量在全局区存放,在类域中为所有对象共享,不属于任何对象,所以int a不占类大小。

有继承关系的类的大小:

class A{	
	int a;
	char c;
	char d;
};

class B:A{
	char e;
	int b;
};


int main(){
	cout<<sizeof(A)<<endl;	//输出8
	cout<<sizeof(B)<<endl;	//输出16
	return 0;
}

A根据上面所说的内存对齐大小为8,B也需要内存对齐,并且继承了A,所以大小为A+B = 16;




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值