c++类 | 类的大小
一、核心原则
类的大小 = 非静态成员变量 按照内存对齐规则排列后的大小 + 虚函数表指针(如果有虚函数)+ 虚基类指针(如果有虚继承)
不影响类大小的因素:
-
✅ 成员函数(普通、静态、虚函数本身)
-
✅ 静态成员变量
-
✅ 静态常量成员变量
二、内存对齐规则(64位编译器)
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对齐三原则:
-
每个成员的偏移量是该成员大小的整数倍
-
结构体总大小是最大成员大小的整数倍
-
成员按声明顺序排列
三、图形化讲解
┌─────────────────────────────────────────────────────────┐│ Class A(无虚函数,无继承) │├─────────────────────────────────────────────────────────┤│ ││ 成员变量(按声明顺序): ││ ││ 偏移0: const int c_var ────┐ ││ 偏移4: int var ├─ 4+4=8字节 ││ 偏移8: char var1 ──┘ ││ 偏移9: [PADDING 3字节] ← 对齐到4的倍数 ││ ││ 总大小 = 12 字节 ││ │└─────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────┐│ Class A(有虚函数) │├─────────────────────────────────────────────────────────┤│ ││ 偏移0: vptr (虚函数表指针) ← 8字节 ││ 偏移8: const int c_var ← 4字节 ││ 偏移12: int var ← 4字节 ││ 偏移16: char var1 ← 1字节 ││ 偏移17: [PADDING 7字节] ← 对齐到8的倍数 ││ ││ 总大小 = 24 字节 ││ ││ 虚函数表(独立于对象): ││ ┌──────────────┐ ││ │ f() 地址 │ ││ │ g() 地址 │ ││ │ h() 地址 │ ││ └──────────────┘ ││ │└─────────────────────────────────────────────────────────┘
四、完整代码示例
// 文件:class_size_demo.cpp// 64位编译器下测试using namespace std;// ==================== 情况1:空类 ====================class Empty {};// ==================== 情况2:只有成员函数 ====================class OnlyFunction {public:void func1() {}void func2() {}static void staticFunc() {}};// ==================== 情况3:只有静态成员 ====================class OnlyStatic {private:static int s_var;static const int SC_VAR = 100;};int OnlyStatic::s_var = 0;// ==================== 情况4:普通成员变量 ====================class NormalMembers {private:char c; // 1字节,偏移0int i; // 4字节,偏移4(1+填充3)double d; // 8字节,偏移8// 总大小:偏移16,最大对齐8,16是8的倍数 → 16字节};// ==================== 情况5:顺序影响大小 ====================class BadOrder {private:char c; // 1字节,偏移0double d; // 8字节,偏移8(1+填充7)int i; // 4字节,偏移16// 总大小:偏移20,对齐到8 → 24字节};class GoodOrder {private:double d; // 8字节,偏移0int i; // 4字节,偏移8char c; // 1字节,偏移12// 总大小:偏移13,对齐到8 → 16字节};// ==================== 情况6:带虚函数 ====================class WithVirtual {private:int a; // 4字节char b; // 1字节public:virtual void vf1() {}virtual void vf2() {}virtual void vf3() {}virtual void vf4() {} // 多个虚函数不影响大小void normalFunc() {} // 普通函数不影响};// ==================== 情况7:虚继承 ====================class Base {int x;};class DerivedVirtual : virtual public Base {int y;};// 虚继承会添加虚基类指针(vbptr),8字节// ==================== 情况8:完整示例 ====================class CompleteExample {private:static int s_var; // 不影响大小const int c_var; // 4字节int var; // 4字节 → 至此8字节char var1; // 1字节 → 9字节,填充到12public:CompleteExample(int temp) : c_var(temp) {}~CompleteExample() {}virtual void f() {} // 添加vptr:8字节virtual void g() {} // 不影响大小virtual void h() {} // 不影响大小// 最终:12 + 填充(4) + 8 = 24字节};// ==================== 主函数测试 ====================int main() {cout << "========== 基本情况 ==========" << endl;cout << "sizeof(Empty): " << sizeof(Empty) << " 字节" << endl;cout << "sizeof(OnlyFunction): " << sizeof(OnlyFunction) << " 字节" << endl;cout << "sizeof(OnlyStatic): " << sizeof(OnlyStatic) << " 字节" << endl;cout << "n========== 普通成员变量 ==========" << endl;cout << "sizeof(NormalMembers): " << sizeof(NormalMembers) << " 字节" << endl;cout << "sizeof(BadOrder): " << sizeof(BadOrder) << " 字节" << endl;cout << "sizeof(GoodOrder): " << sizeof(GoodOrder) << " 字节" << endl;cout << "(优化顺序可以节省空间!)" << endl;cout << "n========== 虚函数影响 ==========" << endl;cout << "sizeof(WithVirtual): " << sizeof(WithVirtual) << " 字节" << endl;cout << "sizeof(CompleteExample):" << sizeof(CompleteExample) << " 字节" << endl;cout << "n========== 指针大小 ==========" << endl;WithVirtual* p;cout << "sizeof(指针): " << sizeof(p) << " 字节" << endl;// 实例化对象CompleteExample ex(4);cout << "n========== 对象大小 ==========" << endl;cout << "sizeof(ex): " << sizeof(ex) << " 字节" << endl;return 0;}
五、预期输出(64位编译器)
========== 基本情况 ==========sizeof(Empty): 1 字节 ← 空类特殊处理sizeof(OnlyFunction): 1 字节 ← 成员函数不影响sizeof(OnlyStatic): 1 字节 ← 静态成员不影响========== 普通成员变量 ==========sizeof(NormalMembers): 16 字节sizeof(BadOrder): 24 字节sizeof(GoodOrder): 16 字节(优化顺序可以节省空间!)========== 虚函数影响 ==========sizeof(WithVirtual): 16 字节 ← 8(vptr) + 4(int) + 1(char) + 3(填充) = 16sizeof(CompleteExample):24 字节========== 指针大小 ==========sizeof(指针): 8 字节========== 对象大小 ==========sizeof(ex): 24 字节
六、关键总结
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
七、快速记忆口诀
⚠️ 版权声明
本文为免费文章,欢迎转载。转载请注明出处:一木科技(https://www.pingquan.vip/2026/05/31/c%e7%b1%bb-%e7%b1%bb%e7%9a%84%e5%a4%a7%e5%b0%8f/),并保留原文链接。
还没有评论,来说两句?