C++ 类大小计算
概述
在 C++ 编程中,我们经常使用 Class 定义类,实现面向对象编程。和 C 语言中的 Struct 结构体一样,定义 Class 类也包括以下作用:
- 决定数据对象需要的内存数量;
- 决定如何 解释内存中的位;
- 决定可使用数据对象执行的操作或方法。
但是,如果想要计算 Class 类的大小,就需要特别小心了!因为类的大小与它的构造函数、析构函数以及其他成员函数无关,只与它的数据成员相关。这和结构体的大小计算不一样!
Class 类大小的相关因素如下表所示:
类型 | 因素 |
---|---|
有关因素 | 普通成员变量,虚函数、继承(单一继承,多重继承,重复继承,虚拟继承) |
无关因素 | 静态成员变量、静态成员函数、普通成员函数 |
下面通过一些简单的示例来加深理解,所有示例均运行在 64 位系统之上,相关代码位于 GitHub 仓库。
示例
1. 空类的大小
示例代码:
#include <iostream>
class CBase
{
};
int main(void)
{
std::cout << "sizeof(CBase) = " << sizeof(CBase)<< std::endl;
return 0;
}
运行结果:
sizeof(CBase) = 1
为什么空的什么都没有是 1 呢?
先了解一个概念:类的实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的 sizeof 为 1。
2. 一般非空类大小
示例代码:
#include <iostream>
class CBase
{
int a;
char *p;
};
int main(void)
{
std::cout << "sizeof(CBase) = " << sizeof(CBase)<< std::endl;
return 0;
}
运行结果:
sizeof(CBase) = 16
在 64 位系统上运行的结果是 16,在 32 位系统上则为 8。因为在 64 位系统上指针的大小是 8 字节,而 32 位系统上指针大小是 4 字节。另外,由于字节对齐的问题,因此输出结果是 16 或者 8。
3. 普通成员函数
示例代码:
#include <iostream>
class CBase
{
int a;
char *p;
void FuncA();
};
int main(void)
{
std::cout << "sizeof(CBase) = " << sizeof(CBase)<< std::endl;
return 0;
}
运行结果:
sizeof(CBase) = 16
输出结果和上一个示例一样,这是因为类的大小与它的构造函数、析构函数和其他成员函数无关,只已它的数据成员有关。
4. 虚函数
示例代码:
#include <iostream>
class CBase
{
int a;
char *p;
virtual void FuncA();
};
int main(void)
{
std::cout << "sizeof(CBase) = " << sizeof(CBase)<< std::endl;
return 0;
}
运行结果:
sizeof(CBase) = 24