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

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

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


文章目录


图文版

在这里插入图片描述

文字版

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

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

核心结论速览

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

详细计算步骤与示例

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

对齐规则:

  1. 第一个成员在偏移量为0的位置。
  2. 后续成员要放到该成员大小的整数倍上。
  3. 最终类的大小要是最大成员大小的整数倍。
classExample1{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. 有虚函数(引入虚表指针)
classBase{int a;virtualvoidfunc(){}};
  • 分析
    • 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. 继承关系
classA{int a;// 4char b;// 1// 实际A的大小:对齐到4,b后面填充3字节,A为8字节};classB:publicA{int c;// 4char d;// 1};
  • 分析
    • 先放基类A的部分:8字节。
    • 再放派生类B的 c:偏移8(刚好是4倍数),占4字节,总偏移12。
    • 再放 d:偏移12,占1字节,总偏移13。
    • 对齐收尾:B中最大对齐数是4(int),当前总大小13不是4的倍数,所以末尾填充3字节到16。
  • 结果16字节
5. 特殊情况:虚继承

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

classA{int x;};// 4字节,对齐后可能8?classB:virtualpublicA{int y;};
  • 结果:通常比普通继承多出一个指针的大小(8字节),用来定位虚基类子对象。情况比较复杂,取决于编译器实现。

总结清单

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

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

简记:

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

总结

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

Read more

Windows在 GitHub 上拉取(Clone)项目到本地电脑的完整步骤

前提: 已经安装下载Git。 步骤 1::获取 GitHub 项目 URL (1)打开 GitHub 网站(已登录),找到你要拉取的项目(如 https://github.com/用户名/仓库名)。 (2)点击绿色的 Code 按钮,选择 HTTPS 方式,复制 URL(如 https://github.com/用户名/仓库名.git)。  步骤 2:使用 Git 命令行拉取项目到本地 (1)在你要放置项目的路径下,打开 命令提示符(CMD): 比如我要放在D:\code\hmdianping这个路径下: (2)

By Ne0inhk
斩获GitHub趋势榜!TrendRadar,让AI帮你24小时洞察全网热点!已有超三万收藏!(部署)

斩获GitHub趋势榜!TrendRadar,让AI帮你24小时洞察全网热点!已有超三万收藏!(部署)

https://github.com/sansan0/TrendRadarTrendRadar 是一个开源的多平台热点聚合与 AI 分析工具,支持监控 35 个平台(如抖音、知乎、B站、华尔街见闻等),通过关键词筛选、自动推送和 AI 对话分析,帮助用户高效处理新闻资讯。项目支持 GitHub 一键部署、Docker 容器化运行,无需编程。项目开源地址:https://github.com/sansan0/TrendRadar,目前该项目已在Github上已收获近3.5w的star,首先感谢开源作者做出的贡献! 本文将基于项目介绍提供的方案,提供一个详细的关于本项目的GitHub Fork 部署(适合无本地环境)方法,协助新用户快速使用。 关键要点 * 部署方式:优先推荐 Docker(一行命令启动),或 GitHub Fork(

By Ne0inhk
GitHub免费开源!World Monitor:开源全球情报仪表盘

GitHub免费开源!World Monitor:开源全球情报仪表盘

一、项目定位:AI驱动的全域态势感知平台 在全球化浪潮与地缘政治格局加速演变的当下,分散的新闻资讯、碎片化的地缘数据、割裂的基础设施监控渠道,让全球局势的洞察者面临“信息过载却又不全”的困境。由开发者cn620主导的开源项目World Monitor,正是为解决这一痛点而生——它是一款基于AI驱动的实时全球情报仪表盘,通过统一的态势感知界面,整合新闻聚合、地缘政治监控、基础设施跟踪三大核心能力,为用户提供一站式、高精度的全球局势洞察工具。 开源地址获取:World Monitor:https://www.gegeblog.top/article/87 二、核心功能模块:三重维度的全球情报覆盖 (一)AI驱动的智能新闻聚合 不同于传统新闻客户端的“被动推送”,World Monitor的新闻聚合能力核心在于AI的深度介入: 1. 多源实时采集:项目通过AI爬虫框架同步抓取全球百余家权威新闻源,包括路透社、美联社、BBC等国际媒体,以及各国官方机构公报、专业地缘政治数据库(如CSIS全球冲突数据库),覆盖英文、中文、阿拉伯文等多语种内容;

By Ne0inhk
如何在VS code中为GitHub Copilot 添加SKill

如何在VS code中为GitHub Copilot 添加SKill

官方链接:Use Agent Skills in VS Code 准备 这里如果要用VS code的Agent Skills记得更新VsCode,下面这个版本及之后的就可以使用 配置Skill Crtl + Shift + P找到设置并打开,搜索chat.useAgentSkills即可 在Github Copilot 聊天框中打开配置自定义智能体,点击+创建新的自定义智能体 之后需要选择是为这个项目创建Skill.md还是所有项目都可用的Skill.md了,之后写入自己的Skill内容就行。 这里是我自己添加的一个Skill.md 添加之后,就会在聊天这里选对应的Skill了,之后就会用这个Skill进行自己的相关分析 使用示例 好啦,快去创建自己的SKill吧!!

By Ne0inhk