去年年底就已经看完这本书了,想着整理读书笔记一直拖延到现在,体验就是没有整理出来的知识过的久了确实容易忘记。
第1章 关于对象
- C++相对于C来说,在布局以及存取时间上的主要的额外负担是由virtual引起的。
- 三种对象模型:
- 简单对象模型:member本身不放在object之中,只有“指向member的指针”才放在object内。该模型没有用在实际产品上。
- 表格驱动对象模型:将class object拆分成data member table和member function table,class object存放指向这两个table的指针。该模型没有用在实际产品上。
- C++对象模型:Nonstatic data members放在每一个class object之内,static data members,static/nonstatic function members则存放在个别的class object之外。
- virtual function的实现机制:
- 每个class产生一组指向该class的virtual functions的指针,存放在一个virtual table里(vtbl)
- 每个class object有一个指针(vptr)指向相关的virtual table。vptr的设定和重置由class的constructor, destructor和copy assignment运算符自动完成。vtbl的第一个slot通常是class关联的type info object(用来支持runtime type identification)
- class对象占用的内存:
- nonstatic data members的总和大小
- 内存对齐损耗
- 因支持virtual function产生的内存损耗
第2章 构造函数语义学
- 以下四种情况,编译器会为未提供默认构造函数的类合成默认构造函数:
带有Default Constructor的Member class Object:类的成员变量有其他类,并且该类有默认构造函数;带有Default Constructor的Base Class:有父类,父类有默认构造函数;带有一个Virtual Function的Class:有虚函数;带有一个Virtual Base Class的Class:有虚基类; 编译器合成的默认构造函数并不会给nonstatic data member(如整数,整数指针,整数数组等)初始化!!!
- 成员初始化列表:
- 初始化顺序是按照成员变量的声明顺序初始化的,编译器优化之后的顺序与成员列表的顺序不一定一致;
- 成员初始化的code会放在实际code之前。
第3章 Data语意学
- 一个virtual base class subobject只会在derived class中存在一份实例,不管它在class在继承体系中出现了多少次。
- static data member存放在程序的数据段里,nonstatic data members存放在class实例里。
第4章 Function语意学
- name mangling的做法编译器并不统一,即生成的名字规范都不一致。编程中link出错的时候报出的奇奇怪怪的函数名其实就是经过name mangling的名字。
- static member function没有this指针:
- 不能直接存取其class的nostatic members;
- 不能声明成const, volatile或者virtual;
- 不需要class object就能调用。
- 一个class只会有一个virtual table,virtual table中含有以下active virtual functions:
- 该class定义的virtual function;
- 继承自base class的virtual function;
- 一个pure_virtual_called()函数实例。
第5章 构造,析构,拷贝语意学
- object生命周期:
- local object从定义到退出其scope;
- global object存活整个程序周期;
- heap object从new开始到delete结束。
- vptr初始化的时间为base class constructors调用结束之后,程序员代码或者member initialization list之前。
- 以下情况下,class对默认的copy assignment operator不会表现出bitwise copy语意,即默认的拷贝赋值函数不太行:
- 当class含有一个member object;
- 当class的base class有一个拷贝赋值函数;
- 当class声明里任何virtual function;
- 当class继承一个virtual base class。
- 析构函数的实际顺序
- 析构函数本体;
- 如果class有member class object且拥有析构函数,则按照声明顺序相反顺序调用;
- 如果有vptr, 需要被重新设定,指向base class的virtual table;
- 如果有任何直接nonvirtual base classes拥有析构函数,会按照声明顺序的相反顺序调用;
- 如果有任何virtual base classes拥有析构函数,并且当前class为最末端的class, 则会按照原来构造的顺序的反顺序被调用。
第6章 执行期语意学
- 编程规范中建议object使用时才定义是因为可以节省非必要的对象产生和摧毁操作。比如说一个object先定义了,但其实后面并没有用到,编译生成的代码其实在定义出就产生了其构造,后面跳出scope又要产生其析构代码,这部分代码是冗余代码。
- new运算符:
- 配置内存;
- 在配置的内存处构造object,赋初值。
第7章 站在对象模型的尖端
- Template不好用,容易出错,debug麻烦,对编程人员要求很高。
- Template函数中涉及类型相关的校验,延迟到实例化操作时才发生。
- 发生exception时,编译器会做如下操作:
- 检验发生throw的操作的函数;
- 决定throw操作是否发生在try区段中;
- 若是,把exception type拿来和每一个catch子句进行比较;
- 如果匹配,流程控制交到catch子句中;
- 如果throw操作没有发生在try区域或者没有匹配到catch子句,编译器需要(a)摧毁所有
active local object(b)将目前的函数从堆栈中unwind掉(c)进入函数调用栈下一个函数中,重复步骤2-5。
- 对一个class指针进行dynamic_cast:
- 如果操作成功,则会返回真正的地址;
- 否则返回0,便是没有cast成功。