本系列文章是对Lippman的《深度探索c++对象模型》(“Inside the c++ object model”)的读书笔记。
1、关于作者Lippman:c++首个编译器的开发者之一,所作的c++方面的书籍有:
《c++ primer》:c++的百科全书,和c++之父的《c++ programming language》齐名。
《Inside the c++ object model》:讲述c++语法的底层机制的。
《Essential c++》:c++入门级的书籍,也可以算是《c++ primer》的一个子集。
2、什么是c++对象模型?
我的理解是,c++语法在编译器背后的实现机制,比如虚函数,为什么可以用虚函数来实现多态,编译器是怎么把虚函数多态调用的。(也不需要理解每一个细节,只需要理解原理即可)
3、为什么要学对象模型?
作者Lippman的理由:它是组件编程(比如:com,corba,som等)模型的基础;学了它能更有效的理由c++来进行编程。
我的看法是:“你应该了解真相,因为真相能使你自由”。
4、《深度探索c++对象模型》这本书讲了c++哪些方面的底层机制?
如下:
构造函数,析构函数,拷贝构造函数,赋值运算符(第二章,第五章)
new和delete的用法,临时对象;对象数组;返回值优化;静态局部变量(第六章)
模板,异常处理,RTTI(第七章)
一般的类,virtual,虚基类,多重继承 等的对象内存布局的详细说明(第三章)
一般的类,virtual,虚基类,多重继承 等的函数调用的详细说明(第四章)
其它...
5、c++语法的底层机制决策的理由
c++有很多决策都基于以下2个因素:
(1)、要尽量和c兼容
(2)、要尽量达到c的效率,这里所说的效率是运行时的时间效率和空间大小,注意是运行时的,不是编译时的,可以这么说,c++是牺牲了编译的时间来换取运行时的高效。
6、一些说明
(1)关于c++语法的底层实现机制,其实c++标准里面并没有规定要怎么实现,比如虚函数,可以用位置查表,也可以用名称查表(具体的机制后面的笔记会说到的),到底用那种机制来实现虚函数,c++标准并没有说明,每个编译器可以有自己的做法;但是另一方面,作伪各家编译器互相竞争的后果,c++的虚函数的底层实现清一色的使用按绝对偏移位置来查找表得方法(这种方法比较高效,当然也有其缺点)。
就是说:由于编译器之间的互相竞争,使得c++背后的实现机制大同小异,都朝着高效的目标前进(如果对这个道理不明白的,可以读一下西方的微观经济学原理,里面有详细的说明,呵呵)
(2)、关于 (时空)效率,通用性 和 间接层 的关系
如果要通用性比较广,那一般都会增加间接层(很多技术问题都是通过增加间接层来解决的),那样就会导致效率的降低;
如果要求高效率,间接层必须要少(甚至不能用间接层),那样会导致其通用性不广;
在c++中的应用体现在以后的多篇文章中。
7、一个例子(书上的例子)
在做笔记之前,先写一个书上的例子,如果你看了这个例子以后,觉得有兴趣,那么,这本书(指的是《Inside the c++ object model》)会非常的适合你(因为这本书就是讲这个方面的)。
上面的函数foobar的函数体,经过编译之后的伪代码如下(注意,是伪代码,因为编译之后的代码是机器码了,这里用c伪代码来说明比较方便)
其实,经过编译之后,foobar函数的转换还不止这些,不过,这些已经足够说明问题了。
如果你看到这里,觉得很好奇:“为什么编译器要这么干?”,那么你就可以往下看了,
下面会为你打开c++底层实现的大门,让你看到c++语言的底层工厂,呵呵。(当然,最好的方法还是看那本书,如果没有时间的话,就浏览一下这个系列里面的文章吧。)
8、学习方法
说一下我学习c++底层模型的办法,就是看书,然后写一些代码,反汇编分析一些例子,这样做,印象会比较深,有些文章为了形象化,画了一些图形,很好懂,一看就“知道”是什么回事,但是这个知道只是直觉而已,说不定一个小时后就忘的一干二净了。所以最好的办法就是写代码,反汇编来验证这些结论,然后自己画画图。这样印象比较深刻一些。
9、例子的运行环境
我的这些笔记里面的例子所用的机器是intel x86 32位下的cpu,平台要么是windows的vs2005,要么是Fedara linux下的g++3.4.3,所以基本的数据类型的大小如下:
bool,char 是1字节; short是2字节; int,long,float是4字节
double,long long是8字节 所有的指针类型:4字节
1、关于作者Lippman:c++首个编译器的开发者之一,所作的c++方面的书籍有:
《c++ primer》:c++的百科全书,和c++之父的《c++ programming language》齐名。
《Inside the c++ object model》:讲述c++语法的底层机制的。
《Essential c++》:c++入门级的书籍,也可以算是《c++ primer》的一个子集。
2、什么是c++对象模型?
我的理解是,c++语法在编译器背后的实现机制,比如虚函数,为什么可以用虚函数来实现多态,编译器是怎么把虚函数多态调用的。(也不需要理解每一个细节,只需要理解原理即可)
3、为什么要学对象模型?
作者Lippman的理由:它是组件编程(比如:com,corba,som等)模型的基础;学了它能更有效的理由c++来进行编程。
我的看法是:“你应该了解真相,因为真相能使你自由”。
4、《深度探索c++对象模型》这本书讲了c++哪些方面的底层机制?
如下:
构造函数,析构函数,拷贝构造函数,赋值运算符(第二章,第五章)
new和delete的用法,临时对象;对象数组;返回值优化;静态局部变量(第六章)
模板,异常处理,RTTI(第七章)
一般的类,virtual,虚基类,多重继承 等的对象内存布局的详细说明(第三章)
一般的类,virtual,虚基类,多重继承 等的函数调用的详细说明(第四章)
其它...
5、c++语法的底层机制决策的理由
c++有很多决策都基于以下2个因素:
(1)、要尽量和c兼容
(2)、要尽量达到c的效率,这里所说的效率是运行时的时间效率和空间大小,注意是运行时的,不是编译时的,可以这么说,c++是牺牲了编译的时间来换取运行时的高效。
6、一些说明
(1)关于c++语法的底层实现机制,其实c++标准里面并没有规定要怎么实现,比如虚函数,可以用位置查表,也可以用名称查表(具体的机制后面的笔记会说到的),到底用那种机制来实现虚函数,c++标准并没有说明,每个编译器可以有自己的做法;但是另一方面,作伪各家编译器互相竞争的后果,c++的虚函数的底层实现清一色的使用按绝对偏移位置来查找表得方法(这种方法比较高效,当然也有其缺点)。
就是说:由于编译器之间的互相竞争,使得c++背后的实现机制大同小异,都朝着高效的目标前进(如果对这个道理不明白的,可以读一下西方的微观经济学原理,里面有详细的说明,呵呵)
(2)、关于 (时空)效率,通用性 和 间接层 的关系
如果要通用性比较广,那一般都会增加间接层(很多技术问题都是通过增加间接层来解决的),那样就会导致效率的降低;
如果要求高效率,间接层必须要少(甚至不能用间接层),那样会导致其通用性不广;
在c++中的应用体现在以后的多篇文章中。
7、一个例子(书上的例子)
在做笔记之前,先写一个书上的例子,如果你看了这个例子以后,觉得有兴趣,那么,这本书(指的是《Inside the c++ object model》)会非常的适合你(因为这本书就是讲这个方面的)。
- class X
- {
- public:
- X(){...} //构造函数
- X(const X& x){...} //拷贝构造函数
- virtual ~X(){...} //虚析构函数
- virtual void foo(){...} //虚函数foo
- ...
- };
- X foobar() //一个全局函数foobar
- {
- X xx;
- X *px = new X;
- //foo() 是虚函数
- xx.foo();
- px->foo();
- ...
- delete px;
- return xx;
- }
- //编译过后,foobar函数体的c++ 伪代码
- void foobar(X & _result)
- {
- //对X xx;语句的转换
- //因为最后返回的是xx,这里用了返回值优化,就是用_result来代替xx
- _result.X::X();
- //对X *px = new X;这条语句的转换
- px = _new( sizeof(X) );
- if( 0 != px )
- px->X::X();
- //对xx.foo()的转换
- foo( &result);
-
- //对px->foo()语句的转换,其中_vtbl就是传说中的虚函数表
- ( *px->_vtbl[2])(px);
- //对delete px的转换
- if( 0 != px )
- {
- ( *px->_vtbl[1] )[px];
- _delete( px );
- }
- //对return xx的转换,返回值已经通过引用参数_result返回了。
- return;
- }
如果你看到这里,觉得很好奇:“为什么编译器要这么干?”,那么你就可以往下看了,
下面会为你打开c++底层实现的大门,让你看到c++语言的底层工厂,呵呵。(当然,最好的方法还是看那本书,如果没有时间的话,就浏览一下这个系列里面的文章吧。)
8、学习方法
说一下我学习c++底层模型的办法,就是看书,然后写一些代码,反汇编分析一些例子,这样做,印象会比较深,有些文章为了形象化,画了一些图形,很好懂,一看就“知道”是什么回事,但是这个知道只是直觉而已,说不定一个小时后就忘的一干二净了。所以最好的办法就是写代码,反汇编来验证这些结论,然后自己画画图。这样印象比较深刻一些。
9、例子的运行环境
我的这些笔记里面的例子所用的机器是intel x86 32位下的cpu,平台要么是windows的vs2005,要么是Fedara linux下的g++3.4.3,所以基本的数据类型的大小如下:
bool,char 是1字节; short是2字节; int,long,float是4字节
double,long long是8字节 所有的指针类型:4字节