欢迎光临
我们一直在努力

怎么计算一个类的大小 (C++)

怎么计算一个类的大小 (C++)


文章目录

  • 怎么计算一个类的大小 (C++)
  • 图文版
  • 文字版
      • 核心结论速览
      • 详细计算步骤与示例
        • 1. 基础计算:空类
        • 2. 只有成员变量(考虑内存对齐)
        • 3. 有虚函数(引入虚表指针)
        • 4. 继承关系
        • 5. 特殊情况:虚继承
      • 总结清单
  • 总结

图文版

在这里插入图片描述


文字版

这是一个非常经典的C++面试题。在C++中,计算一个类的大小并不是简单地将成员变量的大小相加,而是涉及内存对齐、虚函数、继承等多个因素的影响。

以下是计算类大小的核心规则和详细步骤:

核心结论速览

  • 非静态成员变量 是影响大小的主体。
  • 静态成员变量 不属于类实例,存在全局数据区,不计入 sizeof。
  • 成员函数 存在代码段,不计入 sizeof。
  • 虚函数:只要类有虚函数(无论是1个还是多个),类实例中就会有一个虚函数表指针(vptr),在64位系统下通常占8字节,32位下占4字节。
  • 内存对齐:编译器为了提高访问效率,会在成员之间或末尾填充字节,使变量存储在其倍数地址上,并使类总大小是最大对齐数的整数倍。
  • 继承:
    • 空类大小为1字节(为了占位,表示对象存在)。
    • 派生类的大小一般是基类成员 + 派生类新成员,同时也要满足对齐规则。

  • 详细计算步骤与示例

    1. 基础计算:空类

    class Empty {
    // 没有任何成员
    };

    • 大小:1字节
    • 原因:编译器需要给这个类的对象分配一个独一无二的地址,所以会隐式插入1个字节。
    2. 只有成员变量(考虑内存对齐)

    对齐规则:

  • 第一个成员在偏移量为0的位置。
  • 后续成员要放到该成员大小的整数倍上。
  • 最终类的大小要是最大成员大小的整数倍。
  • class Example1 {
    char c; // 1字节
    int i; // 4字节
    };

    • 分析:
      • c 占偏移0。
      • i 占4字节,需要从4的倍数(偏移4)开始存。因此,在 c 后面会有3个字节的填充。
      • 此时已占:1© + 3(填充) + 4(i) = 8字节。
      • 最大对齐数是4,8是4的倍数,无需末尾填充。
    • 结果:8字节(而不是直觉上的 1+4=5)。
    3. 有虚函数(引入虚表指针)

    class Base {
    int a;
    virtual void func() {}
    };

    • 分析:
      • int a:4字节。
      • 虚函数表指针(vptr):64位系统下8字节。
      • 内存对齐:最大对齐数是8(vptr)。a 从偏移0开始占4字节,为了放8字节的vptr,需要在 a 后面填充4字节,使vptr从偏移8开始。
      • 总大小 = 4(a) + 4(填充) + 8(vptr) = 16字节。
    • 结果:16字节。
    4. 继承关系

    class A {
    int a; // 4
    char b; // 1
    // 实际A的大小:对齐到4,b后面填充3字节,A为8字节
    };

    class B : public A {
    int c; // 4
    char d; // 1
    };

    • 分析:
      • 先放基类A的部分:8字节。
      • 再放派生类B的 c:偏移8(刚好是4倍数),占4字节,总偏移12。
      • 再放 d:偏移12,占1字节,总偏移13。
      • 对齐收尾:B中最大对齐数是4(int),当前总大小13不是4的倍数,所以末尾填充3字节到16。
    • 结果:16字节。
    5. 特殊情况:虚继承

    虚继承涉及虚基类指针或类似机制(编译器实现不同,但通常会增加额外开销),用来解决菱形继承问题。

    class A { int x; }; // 4字节,对齐后可能8?
    class B : virtual public A { int y; };

    • 结果:通常比普通继承多出一个指针的大小(8字节),用来定位虚基类子对象。情况比较复杂,取决于编译器实现。

    总结清单

    计算类的大小时,可以按以下清单排查:

  • 基本大小:列出所有非静态成员变量的大小。
  • 虚函数检查:如果有 virtual 函数(包括继承来的),加上虚表指针的大小(8/4字节)。
  • 虚继承检查:如果有虚继承,加上虚基类指针的开销(通常也是8/4字节)。
  • 内存对齐:
    • 计算每个成员相对于起始地址的偏移,插入填充。
    • 最后让总大小是最大对齐数的整数倍,末尾填充。
  • 简记:

    类的大小 = 非静态成员变量大小之和 + 虚函数/虚继承指针开销 + 内存对齐填充字节。

    总结

    这篇文章是作者搜集大量面经和资料这里出来的。感谢你的支持 作者wkm是一名中国矿业大学(北京) 大一的新生,希望得到你的关注 如果可以的话,记得一键三联!

    赞(0)
    未经允许不得转载:171主机测评 » 怎么计算一个类的大小 (C++)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址