【读书笔记】深度探索C++对象模型(更新中

本文通过案例解析C++中虚继承对对象内存布局的影响,包括空类优化、虚基类去重复等特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第三章 Data 语义学

先看栗子

下面通过几个例子大概展示了C++对象内存布局在复杂的继承关系中使用的策略。
开始之前,先来读读下面这段话

C++ Standard 并不强制规定如 “base class subobjects 的排列次序” 或 “不同存取层级的 data
member 的排列次序”这种琐碎细节。它也不规定 virtual functions 或 virtual base classes
的实现细节。C++ Standard 只是说:那些细节由各家厂商自定。

很坑爹吧? >_<
也因此, 代码运行得到的具体数值与系统环境和编译器有关,这对探讨没有影响。
LZ使用mingw-gcc
// ===== 弱爆了的分界线 =====//
先来看第一个case

// case 1
class X {};
class Y: public virtual X {};
class Z: public virtual X {};
class A: public Y, public Z {};
// sizeof X Y Z A -> 1 4 4 8

对于一个空的对象,编译器会为它至少分配一个byte。所以 sizeof(X) = 1。

虚继承 会造成相应的负担,在 derived class 中,这种负担反应在某种形式的指针上。

gcc 的实现上,指针是指向虚表的。
指针是4字节的,所以 Y, Z 的 size 至少是4字节。
聪明的读者一定会问,继承来的基类子对象不是还有一个 byte 吗?
事实的确如此, 在一些机器上,sizeof(Y) = 4(vptr) + 1(base subobject) + 3(alignment) = 8 byte
而像 gcc 这样的编译器, 为 empty virtual base class 提供特殊优化。

在这个策略下,一个 empty virtual base class 被视为 derived class object 最开头的一部分,
也就是说它并没有花费任何的空间, 这就节省了上面所说的编译器所插入的 1 byte。

所以 Y, Z 只包含一个 vptr,size 就是 4 byte。
确定 A 的 size 时需要先解决一个问题,X 在 A 中有几个副本(尽管这里可以优化)?
答案是, 只有 1 个

一个 virtual base class subobject 只会 derived class 中存在一份实体, 不管它在继承体系中出现多少次!

所以 sizeof(A) 的计算方式:
- 共享的唯一的 X 实体,优化后为 0
- base class Y 的大小, 减去因 X 而配置的大小。base class Z 同。4 - 0 + 4 - 0 = 8
- class A 自己的大小: 0
- class A 的对齐: 0
则 sizeof(A) = 8

case 2 和 case 3 的计算方式相同, 作为 excercise 吧。

// case 2
// 与 case 1 唯一的区别是 X 有了一个 char 类型的 data member
class X {char data;};
class Y: public virtual X {};
class Z: public virtual X {};
class A: public Y, public Z {};

// sizeof X Y Z A -> 1 8 8 12
// case 3
class X {int data;};
class Y: public virtual X {};
class Z: public virtual X {};
class A: public Y, public Z {};

// sizeof X Y Z A -> 1 8 8 12

对于 case 4, 并没有用到虚继承,所以也不会有相应的负担。
这种情况,可以简单理解为在 derived class 中直接放入 base class。

// case 4
class X {char data;};
class Y: public X {};
class Z: public X {};
class A: public Y, public Z {};

// sizeof X Y Z A -> 1 1 1 2

Further reading:
C++ 多继承和虚继承的内存布局 详细解释了由gcc编译器实现多继承和虚继承的对象的布局

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值