读书摘要--Inside The C++ Object Model

Chp 1 关于对象


1.1 C++对象模式

    每个类对应的type_info对象,通常由Vtable的第一个slot指向。


1.2 关键字所带来的差异

    如果不是为了努力维持与C的兼容性,C++远可以比现在更简单些。

    C++标准保证,同一个access section中的数据成员,其内存布局同其声明次序保持一致。

    组合,而非继承,才是将C和C++的内存布局结构结合在一起唯一可行的方法。

1.3 对象的差异

    转型操作在大多数情况下不会改变指针所含的地址内容,改变的只是编译器对"指针所指向的内存的大小和内容"的解释方式。

    OO(Object-Oriented)和OB(Object-Based)的区别集中体现在弹性和效率上。


Chp 2 构造函数语意学


2.1 Default Constructor

    被编译器合成出来的Default Constructor的目的是满足编译器的需要,而不是程序的需要

    4种
合成的 non-trivial default constructor

    1.    类中包含对象成员,其具有defalut constructor
    2.    类的base class具有default constructor
    2.    类包含virtual function
    3.    类具备virtual base class

    除此四种情况之外,对于未显式声明default constructor 的类,其在语义上拥有implicit trivial default constructor,但实际上这些constructor并不会被合成出来。
   
    常见的两个误解

    1.任何类如果程序员没有定义default constructor,就会被编译器合成出一个来。

    2.编译器合成出来的default constructor,会将class内的每个data member都设定为默认值。


2.2 copy constructor 语意学

    2.2.1 Default Member-wise Initialization(
递归进行)
   

    类似于default constructor,C++标准也将copy constructor分为 trivial 和non-trivial,只有non-trivial的才会被合成出来

    而判断一个copy constructor是否 trivial的标准则是,class是否具备"bitwise copy semantics"


    2.2.3 不要bitwise copy semantics!

    以下四种情况下,class不具备"bitwise copy semantics"

    1.class包含一个member object,且后者具备copy constructor
    2.class的base class具有copy constructor
    3.class具有virtual function
    4.class具有virtual base class

    2.2.4 重新设定 vptr 指针

    当class具备了vtable后,该class就不再具备 bitwise copy semantics。


2.3 程序转换语意学

    2.3.2 参数的初始化

    语意:copy-initialization

    相同语意前提下的两种实现机制: 1.临时对象 2 直接构建
   
    2.3.3 返回值的初始化

    NRV(Named return value)优化:将copy constructor的调用优化掉,直接对要返回的对象执行各种操作。

    注,通常NRV优化的启用,是以class具备copy constructor为前提的

    一般而言,对于copy constructor 的优化,标准允许实现有很大的自由发挥空间。这样的好处在于获得机器码效率的提升,缺点在于无法安全的在copy constructor 中引入副作用并期望其一定会发生。


2.4 成员初始化列表

    编译器会一一操作初始化列表的成员,以适当的顺序在class的constructor中插入初始化操作,并且保证它们都发生在任何explicit user code 之前。


Chp 3 Data语意学



3.4 继承与Data Member

    一般而言,任何规则碰到virtual base class 都要例外


    3.4.2 加上多态的继承

    vptr在对象中放在什么位置才好?

    选择1  放在class object 的尾部

        优点:保持内存布局与C最大程度的一致
        缺点:不利于实现virtual inheritance
   
    选择2  放在class object 的头部

        优点:易于实现virtual inheritance 和multiple inheritance
        缺点:丧失了和C的内存布局兼容性

    3.4.3 多重继承

    自然多态(natural polymorphism):derived class pointer 到base class pointer 的转换无需编译器对指针指向的地址进行调整

    多重继承的主要麻烦在于derived class object和继承列表中第二个或更靠后的base class object之间的地址转换关系。


    3.4.4 虚拟继承

    一如语意表面的复杂度,编译器要支持虚拟继承,难度也是很高的。

    实现虚拟继承的一般方法: 若一个class拥有virtual base class ,则该class 的对象被分割成两部分: invariant region 和 shared region。
   
    invariant region中的数据,无论后继如何派生,都拥有固定的offset(从object的头部算起)

    shared region 则代表 virtual base class object,这一部分的数据,其位置与后续派生有关,无法直接存取,而只能间接存取

    一般而言,virtual base class 最有效的应用形式是:一个抽象的virtual base,不包含任何data member


3.6 指向data member 的指针

    对于指向 data member 的指针,实际上是data member在 class object中的偏移量;更确切的说,是 offset +1——也就是说,位于object 头部的成员对应的data member pointer 的值为1

    这种
位移从1开始的特性()是基于如下考虑:如何区分"没有指向任何data member"的data member pointer 和 "指向第一个data member "的data member pointer?


Chp 4 Function语意学


4.1 Member Function的各种调用方式

4.1.1 Non-static member function


    C++的设计准则之一,就是non-static member function 的调用至少必须和一般的non-member function 有一样的效率。

    编译器在内部会将 "non-static member function" 转化为等价的"non-member function"

4.1.2 Virtual member function


4.1.3 Static member function

    

4.2 Virtual member functions

    在单一继承体系中, virtual function 机制运转良好;然而在多重继承和虚继承中,对 Virtual Function的支持就不是如此简单了

4.2.1 多继承体系下的Virtual Function
   
    问题的复杂性,来自于第二个及后继base class身上,以及"必须在运行期调整this指针"。

    问题1 virtual destructor

    解决调整this指针较有效率的解决方案是thunk技术,即一小段汇编代码,其负责完成两个任务:(1) 调整this指针 (2) 调用对应的函数

    利用thunk技术, vtable 中的slot就可以继续简单的包含一个指针,这个指针可能直接指向一个virtual function,也可能指向一个相关的thunk(如果该virtual 需要调整this指针的话)。


4.4 指向Member function的指针

    取一个non-static member function的地址,得到的是其在内存中的位置。

    static member function 对应着普通的函数指针,而不是"成员指针"。

    virtual function,multiple inheritance 和virtual inheritance 的存在,会导致member function 指针变得非常复杂。

4.4.1 指向"virtual member function"的指针


    对一个"virtual member function"取地址,得到的是只是vtable的一个索引值,并不是内存地址。



Chp 5 构造、析构、拷贝语意学


    纯虚函数可以被静态调用,但无法动态调用。

5.1 无继承体系下的对象构造

   vptr的初始化由编译器在constructor中插入的代码完成;这些代码位于base class constructor的调用之后,但在任何user code之前。

  
既然标准保证在member initialization list对应的代码执行前,该对象的vptr已经被正确的设置好,那么在member initialization list中调用virtual member function,从vptr的角度来看,是安全的;但如果考虑到可能存在的member之间的依赖关系,这种风格显然是不安全、不推荐使用的。

    一般而言,如果程序中频繁的在函数中返回一个local class object,那么在设计class时,提供一个copy constructor就比较合理,它的存在会触发NRV优化。

5.3 对象复制语意学

    一个class的默认assignment operator,在如下情况下不具备bitwise copy语意

    1.    class含有一个member object,且其具有assignment ooprator
    2.    class的base class 具有 assignment operator
    3.    class包含virtual function
    4.    class有virtual base class
   
    概括的说,non-trivial的assignment operator 不具备bitwise copy semantics。只有non-trivial的assignment operator 才会被编译器合成出来。

    需要注意的时,并不存在与member initialization list 相对应的copy assignment list。

    assignment operator 在 virtual inheritance 下表现不佳。

    任何解决方案如果是以程序操作为基础,导致较高的复杂度和较大的错误倾向,一般公认,这表明语言在该方面存在弱点。

你可能感兴趣的:(读书摘要--Inside The C++ Object Model)