第1章 关于对象
1、C++在布局以及存取时间上的主要的额外负担是由virtual引起的,包括:

a、virtual
function机制,引入vptr以及vtbl,支持一个有效率的"执行期绑定" 
b、virtual
base class,用以实现"多次出现在继承体系中的base class,有一个单一而被共享的实例" 
c、多重继承下,派生类跟第二个以及后续基类之间的转换

2、"指针的类型"会教导编译器如何解释某个特定地址中的内存内容以及其大小(void*指针只能够持有一个地址,而不能通过它操作所指向的object)
3、C++通过class的pointers和references来支持多态,付出的代价就是额外的间接性。它们之所以支持多态是因为它们并不引发内存中任何"与类型有关的内存委托操作(type-dependent
commitment)",会受到改变的,只有他们所指向的内存的"大小和内容的解释方式"而已。

 
 
第2章
构造函数语意学

 
 
第3章
Data语意学
1、类对象大小受三个因素影响

a、virtual
base和virtual function带来的vptr影响 
b、 EBO (Empty
Base class Optimize)空基类优化处理,EBC(Empty Base
Class)占用一个字节,其他含有数据成员的从EBC派生的派生类,只会算自己数据成员的大小,不受EBC一字节的影响 
c、alignment
字节对齐

2、Nonstatic
data members在class object中的排列顺序将和其被声明顺序一样,任何中间介入的static data
members都不会被放进布局之中。
3、静态成员变量
static data members

a、存放在程序的data
segment之中 
b、通过指针和对象来存取member,完全一样,不管继承或者是虚拟继承得来,全局也只存在唯一一个实例 
c、静态常量成员可以在类定义时直接初始化,而 普通静态常量成员只能在.o编译单元的全局范围内初始化

4、非静态成员变量
nonstatic data members

a、 每一个nonstatic
data member的偏移量在编译时即可获知 ,不管其有多么复杂的派生,都是一样的。通过对象存取一个nonstatic
data member,其效率和存取一个C struct member是一样的。 
b、从对象存取obj.x和指针存取pt->x有和差异? 
 
   当继承链中有虚基类时,查找虚基类的成员变量时延迟到了执行期,根据virtual class offset查找到虚基类的部分,效率稍低 
 
   (成员变量的数据存取并没有this指针的变化)

成员变量的具体分布详情参见C++内存分布

 

第4章
Function语意学

1、C++的设计准则之一:nostatic
member function 至少必须和一般的nonmember function有相同的效率。

a、改写函数原型,在参数中增加this指针 
b、对每一个"nonstatic
data member的存取操作"改为由this指针来存取
c、将member
function重写为一个外部函数,经过"mangling"处理(不许要处理的加上 extern "C")

2、覆盖(override)、重写(overload)、隐藏(hide)的区别

重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。

覆盖(也叫重写)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样。
隐藏 是指派生类中的函数把基类中相同名字的函数屏蔽掉了。隐藏与另外两个概念表面上看来很像,很难区分,其实他们的关键区别就是在多态的实现上。

3、静态成员函数
static member functions

a、不能访问非静态成员 
b、不能声明为const、volatile或virtual 
c、参数没有this 
d、可以不用对象访问,直接  类名::静态成员函数  访问

4、C++多态(polymorphism)表示"以一个public
base class的指针(或者reference),寻址出一个derived class object"
5、vtable虚函数表一定是在编译期间获知的,其函数的个数、位置和地址是固定不变的,完全由编译器掌控,执行期间不允许任何修改。
6、vtable的内容:

a、virtual
class offset(有虚基类才有) 
b、topoffset 
c、typeinfo 
d、继承基类所声明的虚函数实例,或者是覆盖(override)基类的虚函数 
e、新的虚函数(或者是纯虚函数占位)

7、执行期虚函数调用步骤

a、通过vptr找到vtbl 
b、通过 thunk技术以及topoffset调整this指针 (因为成员函数里面可能调用了成员变量) 
c、通过 virtual
class offset找到虚基类共享部分的成员 
d、执行vtbl中对应slot的函数

8、多重继承中,一个派生类会有n-1个额外的vtbl(一个可能有n或者n以上个vtbl,看是否有虚基类),它与第一父类共享vtbl,会修改其他父类的vtbl
9、函数性能

Inline
Member > (Nonmember Friend, Static Member, Nonstatic Member) > Virtual
Member > Virtual Member(多重继承) > Virtual Member(虚拟继承)

10、Inline对编译器只是请求,并非命令。inline中的局部变量+有表达式参数-->大量临时变量-->程序规模暴涨

 
第5章
构造、析构、拷贝语意学
1、析构函数不能定义为纯虚函数,以为每个子类的析构函数都会被编译器扩展调用基类的析构函数以及再上层的基类的析构函数。因为只要缺乏任何一个基类的析构函数的定义,就会导致链接失败。
 
   (实际上纯虚函数是可以被定义以及静态调用-类名::函数,但是C++标准为纯虚函数就是代表没有定义)
2、继承体系下带有数据成员的构造顺序

a、虚基类构造函数,从左到右,从顶层到底层。它和非虚基类不同:是由最底层子类调用的。 
b、非虚基类构造函数,按照基类被声明的顺序从左到右调用。它与虚基类不同:是由直接之类调用的。 
c、如果类中有虚表指针,则设置vptr初值,若有新增虚函数或者是覆盖基类虚函数,修改vtbl内容(实际上vtble在编译时,类定义时就已经建立好了) 
d、成员变量以其声明顺序进行初始化构造 
e、构造函数中,用户自定义代码最后被执行

3、如果类没有定义析构函数,那么只有在类中含有成员对象或者是基类中含有析构函数的情况下,编译器才会自动合成一个出来
4、析构函数的顺序跟构造函数的顺序完全相反,如果是为了多态的析构函数,设置为虚析构函数
5、不要在构造函数和析构函数中调用虚函数

 
第6章
执行期语意学
1、尽量推迟变量定义,避免不必要的构造和析构(虽然C++编译器会尽量保证在调用变量的时候才进行构造,推迟变量定义会使得代码好阅读)
2、全局类变量在编译期间被放置于data段中并被置为0

GOOGLE
C++编程规范: 
禁止使用class类型的静态或全局变量,只允许使用POD型静态变量(Plain
Old Data)和原生数据类型。因为它们会导致很难发现的bug和不确定的构造和析构函数调用顺序 
解决: 
改成在static函数中,产生局部static对象

3、如果有表达式产生了临时对象,那么应该对完整表达式求值结束之后才摧毁这些创建的临时对象。有两个例外:1)该临时对象被refer为另外一个对象的引用;2)该对象作为另一对象的一部分被使用,而另一对象还没有被释放。

第7章
站在对象模型的尖端
1、对于RTTI的支持,在vtbl中增加一个type_info的slot
2、dynamic_cast比static_cast要花费更多的性能(检查RTTI释放匹配、指针offset等),但是安全性更好。
3、对引用施加dynamic_cast:1)成功;或2)抛出bad_cast异常;对指针施加:1)成功;2)返回0指针。
4、使用typeid()进行判断,合法之后再进行dynamic_cast,这样就能够避免对引用操作导致的bad_cast异常:
if(typeid(rt) == typeid(rt2))
…。但是如果rt和rt2本身就是合法兼容的话,就会损失了一次typeid的操作性能。

深入探索C++对象模型 读书笔记的更多相关文章

  1. 【C++】深度探索C++对象模型读书笔记--Data语意学(The Semantics of data)

    1. 一个空类的大小是1 byte.这是为了让这一类的两个对象得以在内存中配置独一无二的地址. 2. Nonstatic data member 放置的是“个别的class object”感兴趣的数据 ...

  2. 【C++】深度探索C++对象模型读书笔记--关于对象(Object Lessons)

    前言中的内容: 1.什么是C++对象模型? 1.语言中直接支持面向对象程序设计的部分 2. 对于各种支持的底层实现机制 2. C++ class的完整virtual functions在编译时期就固定 ...

  3. 深度探索C++对象模型读书笔记(2)

    以下测试平台均为vs 2012 指向Data Member的指针测试(1) #include <stdio.h> class Base1 { public: int val1; int v ...

  4. 【C++】深度探索C++对象模型读书笔记--执行期语意学(Runtime Semantics)

    对象的构造和析构: 全局对象 C++程序中所有的global objects都被放置在程序的data segment中.如果显式指定给它一个值,此object将以此值为初值.否则object所配置到的 ...

  5. 【C++】深度探索C++对象模型读书笔记--构造函数语义学(The Semantics of constructors)(四)

    成员们的初始化队伍(member Initia 有四种情况必须使用member initialization list: 1. 当初始化一个reference member时: 2. 当初始化一个co ...

  6. 深度探索C++对象模型读书笔记-第七章站在对象模型的尖端

    Template 模板是在编译时期而非执行时期被计算的.因此其不会带来效率的降低. 1: const Point<float> &ref = 0; 该语句会实例化一个Point的f ...

  7. 深度探索C++对象模型读书笔记-第六章执行期语意学

    在函数中,编译器会帮助将析构函数(Destructor) 安插在相应的位置.对于函数中的局部对象,会将析构函数安插在对象的每一个离开点. 例如: 1: void Function(int a) { 2 ...

  8. 《深度探索C++对象模型》笔记——Data语意学

    Data Member的绑定 inline member functin躯体之内的一个data member绑定操作会在整个class声明完成之后才发生. argument list中的名称还是会在它 ...

  9. 《深度探索C++对象模型》笔记——Function语意学

    member的各种调用方式 C++支持三种类型的member functions:static.nonstatic和virtual. nonstatic member functions会被编译器转换 ...

随机推荐

  1. 阿里云公网IP不能使用

    1.开通专用网络 2.在ECS的安全组 创建 专用网络 3.配置规则 4.快速创建规则,增加自己需要入网的端口号,授权对象写:0.0.0.0/0

  2. django事物回滚

    往数据库写入数据时,不经意间就会写入不完整的数据,我们称之为脏数据.事务管理(transaction)可以防止这种情况发生.事务管理一旦检测到写入异常,会执行回滚操作,即要么写入完整的数据,要么不写入 ...

  3. C#类和结构(1)

    1.结构功能特性? 实现代码? 结构用struct关键字定义的,与类类似,但有本质区别.结构实质是一个值类型,它不需要对分配的. 结构的特性: (1).结构作为参数传递时,是值传递. (2).结构的构 ...

  4. 使用jQuery方法做任务左右栏移动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 016_笼统概述MapReduce执行流程结合wordcount程序

    数据传输<key,value>     File-->  <key,value>  -->map(key,value)  --> mapResult<k ...

  6. PHP连接到mysql的方法--mysqli和PDO

    php连接到mysql数据库,经典的方式就是使用mysql_connect(),具体代码如下: mysql_connect($db_host, $db_user, $db_pass) or die(m ...

  7. cocos2d关于glew32.lib错误(转)

    应项目需要使用cocos2d-x开发,又要学习新东东了.·cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,用C++重写cocos2d-iphone引擎的一个开源项目,想了解更多的童鞋美去百 ...

  8. 移植opencv2.4.9到android过程记录

    http://blog.csdn.net/brightming/article/details/50606463 在移植到arm开发板的时候已经说过,OpenCV已经为各平台准备了一套cmake交叉编 ...

  9. display:inline-block 间隙

    IE6/7是不支持display:inline-block属性,只是让其表现的跟inline-block一样,尤其对于inline水平的元素,其表现度可以用perfect一词来形容了. 对于IE8+以 ...

  10. php数组函数-array_diff()

    array_diff()函数返回两个数组的差集数组.该数组包括了所有在被比较数组中,但是不在任何其他参数数组中的键值在返回数组中,键名保持不变. array_diff(array1,array2,ar ...