C++类对象占用空间大小计算

本文详细解析了C++中类对象占用的空间大小计算方法,包括基本数据类型对齐规则、不同情况下类成员变量的内存分配及虚函数的影响。

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

0x1、知识点

1、一个类对象所占据的内存空间由它的数据成员(非静态成员)所占据的数据空间总和决定(需要考虑对齐);

2、类的成员函数(包括静态、非静态)、虚函数本身不占据对象的内存空间; 

3、空类、单一继承的空类、多继承的空类所占用空间大小为 1 ;

1.1、基本数据类型大小:

基本数据类型
bool1个字节
char1个字节
short2个字节
int4个字节
long4个字节
float4个字节
double8个字节

0x2、详细介绍

2.1、普通类,无继承

        先看代码:

class A {
public:
	A() {
	}
private:
	int a;
	int b;
	char c;
	int d;
	char e[1];
};
int main()
{
	A a;
	size_t aa = sizeof(a);
	printf("aa = %d\n", aa);
    return 0;
}
上述代码类A中有五个私有成员变量,按照内存大小对齐来计算:
int a --> 4字节
int b --> 4字节
char c --> 4字节
int d --> 4字节
char e --> 4字节
大小总计:20 字节

可能有人会有这个疑问:这个对齐是按照什么对齐的呢?答案就是按照成员变量中类型大小最大的来计算,即如果是int那么按照 4 字节对齐,如果是double类型的变量则是按照 8 字节对齐。而且需要注意的是,不要以为只有单字节的char在最后,且后面没有了其他数据成员就不用对齐了,依然是要对齐的!

上面的计算是否很简单?现在我们再来看成员变量中有double类型的类大小如何计算:

class A {
public:
	A() {
	}
private:
	int a;
	int b;
	char c;
	double d;
	char e[1];
 	int f;
 	char g;
 	int h;
};
int main()
{
	A a;
	size_t aa = sizeof(a);
	printf("aa = %d\n", aa);
    return 0;
}

上述代码类A中有八个私有成员变量,按照内存大小对齐来计算:

int a --> 4个字节
int b --> 4个字节
char c --> 8个字节
double d --> 8个字节
char e --> 4个字节
int f --> 4个字节
char g --> 4个字节
int h --> 4个字节
大小总计:40 字节
大家看到,同样是 char 类型的数据,凭什么 "char c"就是占 8 个字节,而 "char e" 和 "char g" 就只占 4 个字节? 这是为什么呢?如之前所说的,对齐值是按照最大的数据类型大小来算的,至于为什么 "char c" 是8个字节而 "char e" 和 "char g" 是4字节的原因是因为 "char e" 4 字节对齐后加上 "int f" 4个字节后刚刚凑够 8 个字节了,他们俩搭伙凑够 8 字节也正符合当前 8 字节对齐的规律。而 "char c" 很孤单,没人和它搭伙,所以就自己凑出 8 字节咯!

2.2、普通类,有继承

        如果只是单纯的普通类,且没有虚函数和虚继承的话,那么子类会继承父类所有成员。但是虽然继承了,如果父类中的成员是私有的话是无法被访问的。所以在这种情况下的继承,子类的大小就是父类的大小 + 子类成员大小,而且子类中同样也继承了父类中的对齐规则,8 字节对齐的依然还是 8 字节对齐。

class A {
public:
	A() {
	}
private:
	int a;
	int b;
	char c;
	double d;
	char e[1];
  	int f;
};

class B :public A {
private:
	char a;
	int b;
};

int main()
{
	A a;
	size_t aa = sizeof(a);
	B b;
	size_t bb = sizeof(b);
	printf("aa = %d\nbb = %d\n", aa, bb);
    return 0;
父类 A 的大小:
int a --> 4 字节
int b --> 4 字节
char c --> 8 字节
double d --> 8 字节
char e --> 4 字节
int f --> 4 字节
大小总计:32 字节

子类 B 的大小:

char a --> 4 字节
int  b --> 4 字节
父类 A --> 32 字节
大小总计:40 字节

2.3、有虚函数的类,有继承

        有虚函数的类,除了自身所有成员变量的大小外,还要加上由于有虚函数而被编译器生成的虚函数表指针,这个指针的大小同样受最大类型对齐影响,而且这个虚函数表指针的大小是在所有成员大小计算完后加上的,所以如果是最大类型为 int 的,则是所有成员大小之和之上再加 4 。同理,如果最大类型是double,则是加 8 。
class A {
public:
	A() {
	}
	virtual void fun() {}
private:
	int a;
	int b;
	char c;
	double d;
	char e[1];
  	int f;
};

class B :public A {
public:
	virtual void fun1() {}
private:
	char g;
	int h;
};
int main()
{
	A a;
	size_t aa = sizeof(a);
	B b;
	size_t bb = sizeof(b);
	printf("aa = %d\nbb = %d\n", aa, bb);
    return 0;
}

父类 A 的大小:

int a --> 4 字节
int b --> 4 字节
char c --> 8 字节
double d --> 8 字节
char e --> 4 字节
int f --> 4 字节
虚函数表指针大小 --> 8 字节
大小总计:40 字节

子类 B 的大小:

char g --> 4 字节
int h --> 4 字节
父类 A 的大小 --> 40 字节
大小总计: 48 字节

需要注意的是:虽然子类也有自己的虚函数,但是它继承了父类的虚函数表指针,也等于继承了父类的虚函数表。除非父类中没有虚函数,那么子类是不会自己再生成一个虚函数表的。它自己的虚函数地址会加入到从父类继承过来的虚函数表中。

0x3、最后

        还有关于虚继承的内容之后再添加上,关于《C++类对象占用空间大小计算》到此就结束了。本人才疏学浅,文中内容虽经过VS2015编译测试,但也可能难免疏忽出错,如果看官发现了错误还请及时留言指正!谢谢!

        如果您觉得这篇文章对您有所帮助,还请给个点赞鼓励!谢谢!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值