您的位置:首页 > 编程语言 > C语言/C++

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

2015-07-25 18:27 411 查看

第三章 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编译器实现多继承和虚继承的对象的布局
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: