如何计算类对象的大小
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
char _a;
};
类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算
一个类的大小?
类对象的存储方式猜测
- 对象中包含类的各个成员
缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一
个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。那么
如何解决呢?
- 代码只保存一份,在对象中保存存放代码的地址
- 只保存成员变量,成员函数存放在公共的代码段
对于上述三种存储方式,那计算机到底是按照那种方式来存储的?
我们再通过对下面的不同对象分别获取大小来分析看下:
#include<iostream>
using namespace std;
class A1 {
public:void f1() {}
private:int _a;
};
// 类中仅有成员函数
class A2 {
public:void f2() {}
};
// 类中什么都没有---空类
class A3
{};
int main()
{A1 a1;A2 a2;A3 a3;cout << sizeof(a1) << endl;cout << sizeof(a2) << endl;cout << sizeof(a3) << endl;return 0;}
打印结果:
结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
结构体内存对齐规则
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8。
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
编译器按以上原则处理结构体:
struct Example {char a; // 1字节int b; // 4字节,需4字节对齐double c; // 8字节,需8字节对齐
};
实际内存布局(假设64位系统):
0-7: [a][padding][b....]
8-15: [c........]
总大小=16字节(而非1+4+8=13)
内存对齐的基本原理
- 数据总线特性:CPU通过固定位宽(如32位/64位)的总线访问内存。例如32位系统每次读取4字节,若数据跨越两个总线位宽单元,需要多次读取
- 硬件限制:某些架构(如ARMv5)直接禁止非对齐访问,触发总线错误
- 缓存优化:对齐数据更易填满完整的缓存行(通常64字节),减少缓存失效概率
内存对齐通过空间换时间的策略,平衡了硬件特性和软件效率。理解这一机制有助于写出高性能、跨平台兼容的代码结构。