• 【深度探索C++对象模型读书笔记】【第3章】Data语意学


    1、例子,用VS 2013编译器

    #include<iostream>
    using namespace std;
    
    class X{};
    class Y :public virtual X{};
    class Z :public virtual X{};
    class A :public Y, public Z{};
    
    int main(){
    	cout << sizeof(X) << endl;// 1
    	cout << sizeof(Y) << endl;// 4
    	cout << sizeof(Z) << endl;// 4
    	cout << sizeof(A) << endl;// 8
    
    	system("pause");
    	return 0;
    }
    

    注意:空类有隐藏的1byte的大小,是被编译器安插进去的一个char,以使这一class的两个objects得以在内存中配置独一无二的地址。


    2、类对象大小受到三个因素的影响:

    1)语言本身所造成的额外负担。当语言支持virtual base classes时就会导致一些额外负担。

    2)编译器对于特殊情况所提供的优化处理。

    3)Alignment的限制。

    3、virtual baseclass subobject只会在derived class中存在一份实例,不管它在class继承体系中出现了多少次。

    4、  C++standard并不强制规定base class subobjects的排列顺序或不同存取层级的data members的排列顺序这种琐碎细节,它也不规定virtual function以及virtual base classes的实现细节。

    5、 C++对象模型尽量以空间优化和存取速度优化来表现nonstatic data members,并保持和C语言struct数据配置的兼容性。它把数据直接存放在每一个class object中,对于继承而来的nonstatic data members,不管是virtual或nonvirtual base class也是如此。至于static data members则被放置在程序的一个global data segment中,不会影响个别class object的大小。

    6、inlinemember function躯体内的一个data member绑定操作,会在整个class声明完成后才发生,而argument list中的名称还是会在它们第一次遭遇时被适当地决议resolved完成。请总是把nested type声明放在class的起始处。

    7、C++ Standard要求,在同一个accesssection(private、public、protected)中,members的排列只需满足“较晚出现的members在class object中有较高的地址”这一条件即可。也就是说各个members并不一定的连续排列,alignment可能需要的bytes以及编译器可能合成一些供内部使用的data members都可能介于被声明的members之间。

    8、C++ Standard也允许编译器将多个accesssections之中的data members自由排列,不必在乎它们出现在class声明中的次序。

    9、每一个staticdata member只有一个实例,存放在程序的data segment之中。每次程序取用static member时,都会被内部转化为对该唯一extern实体的直接参考操作。

    10、取一个staticdata member的地址,会得到一个指向其数据类型的常量指针,而不是指向其class member的指针。

    11、如果两个类都声明了同一个静态数据成员,那么当它们放在程序的data segment时,会导致名称冲突。编译器会对每一个静态数据成员编码,有多少个编译器,就有多少种name-mangling做法,任何name-mangling做法都有两个重点:

    1)一种算法,推导出独一无二的名称;

    2) 万一编译系统或者环境工具必须和使用者交谈,那些独一无二的名称可被轻易推导回原先的名称。

    12、欲对一个nonstaticdata member进行存取操作,编译器需要把class object的起始地址加上data member的偏移量offset。

    13、  在C++继承模型中,一个derivedclass object所表现出来的东西,是其自己的members加上其base classes members的总和。C++ Standard并未规定derived class members和base classes members的排列顺序。在大部分编译器上,除virtual base class外,base class members总是先出现。

    14、如果只有继承,没有多态,C++语言保证是:“出现在derivedclass 中的base class subobject有其完整原样性”。

    15、加上多态后:

    1)创建virtualtable,用来存放声明的每一个虚函数的地址。

    2)创建vptr,提供执行期的链接,使每一个object能够找到对应的virtual table。 

    3)加强construct,使它能为vptr设定初值,让它指向class所对应的virtual table。

    4)加强destructor,使它能够抹消指向class相关virtual table的vptr。

    16、多重继承的复杂度在于derivedclass和其上一个base class乃至上上一个base class之间的非自然关系,其主要问题发生在derived class objects和其第二或后继的base class objects之间的转换。对一个多重派生对象,将其地址指定给最左端base class的指针,情况将和单一继承相同,而第二个或后继的base class的地址指定操作则需要修改地址,加上或减去(若是downcast)介于中间的base class subobjects的大小。C++ Standard并未要求多重继承时derived class object中各个base class subjectes的排列顺序,目前各个编译器都是根据声明顺序来排列它们。

    17、class内如果内含一个或多个virtualbass class subobjects,将被分割为两部分:一个不变局部和一个共享局部。不变局部总是拥有固定的offset,其数据用以指定共享局部的位置,可以直接存取;而共享局部表现的就是virtual base class subobject,其位置会因为每次的派生操作而变化,只可间接存取。各家编译器实现技术之间的差异就在于间接存取的方法不同。

    18、取一个nonstaticdata member的地址,将会得到它在class的offset;而取一个static data member的地址或者取一个绑定于真正class object身上的data member的地址,将会得到该member在内存中的真正地址。



  • 相关阅读:
    BZOJ3503: [Cqoi2014]和谐矩阵
    不常用的黑科技——「三元环」
    解题:八省联考2018 劈配
    解题:EXNR #1 金拱门
    解题:八省联考2018 林克卡特树
    解题:AT2064 Many Easy Problems&EXNR #1 T3 两开花
    解题:SPOJ 422 Transposing is Even More Fun
    解题:SDOI 2017 硬币游戏
    解题:CTSC 2006 歌唱王国
    解题:BZOJ 3622 已经没有什么好害怕的了·
  • 原文地址:https://www.cnblogs.com/ruan875417/p/4558283.html
Copyright © 2020-2023  润新知