最近花时间读了一下《深入探索C++内存模型》,这本带我了解到了更底层的C++知识。

这本书从C++语言各种特性的实现机制上进行细致剖析,进而总结出对软件开发具有指导意义的经验和结论。这本书的目标群体是具有开发经验的中高级开发人员,其内容的专业性是不容质疑的。

从我的阅读感受上讲,它相对比那些一般的技术文档要耗时耗力。全书共三百多页,粗略地估算了一下,我却用了一个月的空余时间才读完。我会将读书笔记整理成博文,这样能够加深记忆,也方便以后查阅。

1 简介

书的原作者是Stanley B. Lippman,我读的是候捷翻译的中文版本。从书的序言和前言了解到,这两个作者都是在C++语言发展的早期做过贡献的,他们都与C++之父Bjarne共同开发过早期版本的C++编译器。这本书还带给我预期之外的收获,让我了解到C++语言较早期的发展过程,了解到在语言的初创期开发者门做出的努力。C++这门语言不断地发展演变,再到最近推行的C++11新标准,我作为使用这门语言的开发者,也能够感受到C++开发语言正在不断进化和完善。

对于英文资料,我一般都会选择原版,因为翻译后的中文版本一般都会比较生硬,不如原版容易理解。而候捷翻译的这个版本让我看到了作为一名翻译作者付出的努力,中文版修正了很多原书的错误,也为了方便读者理解做了很多润色。

2 第一章 关于对象 (object lessons)

C++在布局以及存取时间上主要的额外负担是由virtual引起,包括:

  • virtual function 机制:用以支持一个有效率的“执行期”绑定(runtime binding)
  • virtual base class 虚基类:用以实现“多次出现在继承体系中的base class,有一个单一而被共享的实体”
  • multiple inheritance 多重继承:在“一个derived class和其第二或后继之base class的转换”时

2.1 对象模型

C++对象模型的设计需要从空间使用效率、程序执行效率进行考虑,同时还兼顾了对C语言中 struct 的支持。C++对象模型的特点主要有:

  • nonstatic data members 被配置于每一个 class object 之内
  • static data members 被存放再所有的 class object 之外
  • static 和 nonstatic function members 被放在所有的 class object 之外
  • 每个 class 产生出一堆指向 virtual functions 的指针,放再表格之中,这个表格被成为 virtual table(vtbl)
  • 每个 class object 被添加一个指针,指向对应的 virtual table,通常这个指针被称为 vptr。vptr 的设置(setting)和重置(resetting)都由每个 class 的 constructor 、 destructor 和 copy assignment 运算符自动完成。
  • 每个 class 用于支持 RTTI(runtime type identification) 所关联的 type_info object 通常存放在 virtual table 的第一个 slot 处

2.2 虚继承和虚基类

在虚继承的情况下,base class 不管再继承串链中被派生(derived)多少次,永远只会存在一个实体(称为 subobject)。Virtual base class 的原始模型是在 class object中为每一个有关联的 virtual base class 加上一个指针,形成一个表格结构,在书中的3.4节有消息讨论。

2.3 classstruct 关键字

struct 关键字默认提供了 public 访问限定。除此之外,从 C++ 编译器的语义分析器(parser)来看,二者并没有本质区别。在C++中引入 class 并不只是关键词,还有它所支持的封装和继承的哲学。

C语言中的 struct 关键字有很多技巧性用法,书中给出了内含变长数组的结构体为例,但这种用法在C++中并不推荐使用。

2.4 类的对象

C++程序设计模型直接支持三种 programming paradigms (C++是一种多范式编程语言):

  1. 程序模型,procedural model
  2. 抽象数据类型模型,abstract data type model, ADT
  3. 面向对象模型,object oriented model

为了表现一个 class object 需要的内存大小:

  • 其 nonstatic data members 的总和大小
  • 加上任何由于 alignment 而填补(padding)的空间,这个 padding 可能存在于 members 之间,也可能存在于集合体边界
  • 加上为了支持 virtual 而由内部产生的额外负担(overhead)

多态是一种威力强大的设计机制,允许你继一个抽象的 public 接口之后,封装相关的类型。需要付出的代价就是额外的间接性,不论是再“内存的获得”或是再“类型的决断”上。C++ 通过 class 的 pointers 和 references 来支持多态,这种程序设计风格就称为“面向对象”。

C++也支持具体的ADT程序风格,如今被称为 object base (OB)。一个 OB 设计可能比一个对等的 OO 设计速度更快而且空间更紧凑。速度更快是因为所有的函数调用操作都在编译时期解析完成,对象构建起来时不需要设置virtual机制;空间紧凑是因为每一个 class object 不需要负担传统上为了支持 virtual 机制而需要的额外负荷。不过 OB 设计比较没有弹性。

OO 和 OB 设计策略都有他们的拥护者和批评者。在弹性(OO)和效率(OB)之间常常存在着取与舍。

(全文完)