c++类 | 类的大小

文章工具

一、核心原则

类的大小 = 非静态成员变量 按照内存对齐规则排列后的大小 + 虚函数表指针(如果有虚函数)+ 虚基类指针(如果有虚继承)

不影响类大小的因素:

  • ✅ 成员函数(普通、静态、虚函数本身)

  • ✅ 静态成员变量

  • ✅ 静态常量成员变量


二、内存对齐规则(64位编译器)

类型
大小
对齐要求
char
1
1
short
2
2
int
4
4
float
4
4
double
8
8
指针
8
8
long long
8
8

对齐三原则:

  1. 每个成员的偏移量是该成员大小的整数倍

  2. 结构体总大小是最大成员大小的整数倍

  3. 成员按声明顺序排列


三、图形化讲解

┌─────────────────────────────────────────────────────────┐│  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位编译器下测试
#include <iostream>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字节,偏移0    int i;      // 4字节,偏移4(1+填充3)    double d;   // 8字节,偏移8    // 总大小:偏移16,最大对齐8,16是8的倍数 → 16字节};
// ==================== 情况5:顺序影响大小 ====================class BadOrder {private:    char c;     // 1字节,偏移0    double d;   // 8字节,偏移8(1+填充7)    int i;      // 4字节,偏移16    // 总大小:偏移20,对齐到8 → 24字节};
class GoodOrder {private:    double d;   // 8字节,偏移0    int i;      // 4字节,偏移8    char 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 字节

六、关键总结

场景
大小(64位)
说明
空类
1
保证不同对象有不同地址
只有函数
1
函数不占用对象空间
只有静态成员
1
静态成员共享,不属对象
普通成员变量
成员总和对齐后大小
遵循结构体对齐
有虚函数
上述 + 8
添加虚函数表指针(vptr)
虚继承
上述 + 8
添加虚基类指针(vbptr)
多虚函数
同上
所有虚函数共用一个vptr
场景
大小(64位)
说明
空类
1
保证不同对象有不同地址
只有函数
1
函数不占用对象空间
只有静态成员
1
静态成员共享,不属对象
普通成员变量
成员总和对齐后大小
遵循结构体对齐
有虚函数
上述 + 8
添加虚函数表指针(vptr)
虚继承
上述 + 8
添加虚基类指针(vbptr)
多虚函数
同上
所有虚函数共用一个vptr

七、快速记忆口诀

⚠️ 版权声明

本文为免费文章,欢迎转载。转载请注明出处:一木科技(https://www.pingquan.vip/2026/05/31/c%e7%b1%bb-%e7%b1%bb%e7%9a%84%e5%a4%a7%e5%b0%8f/),并保留原文链接。