当前位置: 首页 > news >正文

【C++】揭秘类与对象的内在机制

【C++】揭秘类与对象的内在机制

在 C++ 中,“类”和“对象”是最核心的概念,但很多人只是会用,却不知道它们在内存里到底是怎么布局的、编译器到底做了什么、虚函数表是怎么回事、this 指针藏在哪里……

这篇我们从底层视角彻底把类与对象的内存模型、构造/析构机制、虚函数机制、this 指针、多重继承下的布局等讲透。

一、类与对象在内存中的本质区别

一句话概括:

  • 是蓝图(类型定义),不占内存(只存在于编译期符号表)
  • 对象是根据蓝图实例化出来的实体,真正占用内存
classPerson{public:string name;// 8 字节(64位系统,大多数实现)intage;// 4 字节doubleheight;// 8 字节};Person p1;// p1 是对象,占 8 + 4 + 8 = 20 字节(可能有对齐,实际 24 字节)Person*p2=nullptr;// p2 是指针,只占 8 字节

结论:定义类不耗内存,创建对象才真正分配内存。

二、最简单的对象内存布局(无虚函数)

classStudent{public:string name;// 通常 24 字节(含 SSO 小字符串优化)intscore;// 4chargrade;// 1// 可能有 padding(内存对齐)};

典型 64 位系统内存布局(考虑对齐):

偏移 内容 大小 0 name 24 字节(std::string 常见实现) 24 score 4 字节 28 grade 1 字节 29~31 padding 3 字节(对齐到 4 字节) 32 (下一个成员或结束)

总大小:通常 32 字节(而非 24+4+1=29)

内存对齐规则(非常重要):

  • 每个成员按自己的对齐要求对齐(int 4 字节,double 8 字节等)
  • 整个结构体大小是对齐到最大成员的对齐边界

三、带虚函数的对象内存布局(虚表指针)

classAnimal{public:virtualvoidspeak(){cout<<"Animal\n";}virtualvoideat(){cout<<"Eat\n";}intage=0;};Animal a;

关键点:只要类中有虚函数,编译器就会在对象内存布局的最前面插入一个虚表指针(vptr),占 8 字节(64 位系统)。

内存布局变成

偏移 内容 0 vptr(指向该类的虚函数表 vtable) 8 age(4 字节 + 4 字节 padding)

虚表(vtable)是什么?

  • 每个有虚函数的(不是对象)在程序启动时(或第一次使用前)会生成一张虚函数表
  • 虚表是一个函数指针数组,按声明顺序存放虚函数地址
  • 同一个类的所有对象共享同一张虚表
Animal 的虚表(示例): 0: Animal::speak 的地址 1: Animal::eat 的地址

结论
含虚函数的类,每个对象都会多出 8 字节(vptr),指向类的虚表。

四、this 指针到底是什么?

this是一个隐式参数,每个非静态成员函数都自动带有一个隐藏的 this 指针。

voidspeak(){cout<<age;}// 编译器看到的真实样子voidspeak(Animal*constthis){cout<<this->age;}

调用方式

Animal a;a.speak();// 编译器自动传入 &a 作为 this

this 的类型

  • 在非 const 成员函数中:T* const this
  • 在 const 成员函数中:const T* const this

五、继承下的内存布局(单继承)

classAnimal{public:virtualvoidspeak(){}intage=1;};classDog:publicAnimal{public:virtualvoidspeak()override{cout<<"Woof\n";}intlegs=4;};

Dog 对象的内存布局(典型实现):

偏移 内容 0 vptr(指向 Dog 的虚表) 8 age (从 Animal 继承) 12 legs (Dog 自己的成员)

Dog 的虚表

0: Dog::speak (覆盖了 Animal::speak) 1: Animal::eat (如果有)

六、多重继承 + 虚继承下的布局(最复杂部分)

多继承时,每个基类可能有自己的 vptr,导致对象中有多个 vptr

classA{virtualvoidf();inta;};classB{virtualvoidg();intb;};classC:publicA,publicB{intc;};

C 对象可能的布局(非虚继承):

0 vptr for A 8 a 12 vptr for B 20 b 24 c

虚继承(virtual inheritance)会引入vbptr(虚基表指针),解决菱形继承问题。

虚继承布局(更复杂,包含偏移量调整):

  • 包含 vbptr(虚基表指针)
  • 虚基表记录虚基类的偏移
  • 虚函数表也会有额外的调整(thunk)

一句话总结
多继承 + 虚继承是 C++ 中最复杂的内存布局,强烈建议能不用就不用(现代设计倾向于组合优于继承)。

七、构造与析构的底层顺序

classBase{public:Base(){cout<<"Base ctor\n";}~Base(){cout<<"Base dtor\n";}};classDerived:publicBase{public:Derived(){cout<<"Derived ctor\n";}~Derived(){cout<<"Derived dtor\n";}};

构造顺序:从基类 → 派生类
析构顺序:从派生类 → 基类(与构造完全相反)

带成员变量的顺序

  1. 基类构造
  2. 成员变量按声明顺序构造(不是初始化列表顺序)
  3. 派生类构造体执行

析构完全相反

八、总结:类与对象内存机制核心要点

  1. 普通类:成员按声明顺序 + 内存对齐布局
  2. 含虚函数的类:对象开头插入 vptr(8 字节),指向类的虚表
  3. this 指针:隐式传入的指向当前对象的指针
  4. 继承:子类对象包含基类部分(前置布局)
  5. 多继承:可能有多个 vptr
  6. 虚继承:引入 vbptr + 虚基表,解决菱形问题
  7. 构造顺序:基类 → 成员 → 自身
  8. 析构顺序:自身 → 成员 → 基类

最后送你一个快速判断内存布局的口诀

  • 有虚函数? → 多 8 字节 vptr
  • 多继承? → 可能多个 vptr
  • 虚继承? → 更复杂,出现 vbptr
  • 成员变量? → 按声明顺序 + 对齐
  • 空类? → 大多数编译器占 1 字节(避免地址相同)

想继续深入哪个部分?
比如:

  • 虚函数表具体长什么样(可以用 gdb 或 dump 看)
  • 多继承/虚继承下的 this 指针调整
  • 成员函数的地址到底存哪里
  • 空基类优化(EBO)
  • 虚析构函数为什么必须有

欢迎继续问~

http://www.jsqmd.com/news/355280/

相关文章:

  • 现代python安装与管理方法——python-manager
  • 医疗设备测试:FDA法规与ISO 13485整合
  • Protobuf协议
  • 学生党平价首选!高性价比油皮洁面推荐,敏感肌也能放心用 - 资讯焦点
  • COPPA标准在APP测试中的技术实施框架
  • 内蒙古大学计算机研究生老导师详情
  • 网址链接
  • 开源许可证合规:测试工具选型的法律陷阱
  • 【嵌入式就业5】硬件体系与RTOS核心机制:从ARM架构到实时调度
  • GDPR下的测试日志管理:构建合规高效的自动化防护体系
  • 翠韵逐光,琼岛启新 佛山翠升生珠宝翡翠三亚海棠盛大启幕 - 中媒介
  • 2026年防腐蚀工业载冷剂厂家推荐指南 - 资讯焦点
  • 2026国内最新家电售后外包/家电售后安装维修服务商首选推荐神州联保:数字化服务引领者,神州联保值得信赖 - 品牌推荐2026
  • Kong + Consul 实现 网关服务和服务发现
  • 2026年软件测试公众号热度趋势与AI框架实战解析
  • 十四连冠的底蕴:解码格力中央空调全产业链掌控力 - 资讯焦点
  • C语言内存函数(二)
  • 打瓦上分神器!2026高性价比鼠标推荐:罗技G304X秒鲨领衔,中小手玩家必看 - 资讯焦点
  • celery库(python包)与celery 容器的问题
  • 当AI成为赛场“鹰眼”:姿态估计模型如何重塑体育公平
  • 天硕(TOPSSD)技术解析:工业级SSD如何从FTL层面杜绝移动设备断电风险? - 资讯焦点
  • 糖友厨房无糖健康饼干推荐 - 资讯焦点
  • CANN-LLM:基于昇腾 CANN 的高性能、全功能 LLM 推理引擎
  • 东三省优质钢化玻璃供应商推荐榜 - 资讯焦点
  • ‌自动化伦理框架:防止AI过度依赖的设计原则
  • 编译器级优化实战:基于 CANN `tbe-scheduler` 的自定义算子自动调度
  • 深度学习:5层CNN实现图片分类(MATLAB版)
  • 2026市政护栏优质供应商推荐榜 - 资讯焦点
  • 厨余垃圾处理器选购技巧?余库/爱适易/海尔等热门品牌分享,买前先看不踩雷! - 资讯焦点
  • CANN-LLM WebUI:打造国产 LLM 推理的“驾驶舱