C++对象模型笔记:概述

本系列文章是对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》)会非常的适合你(因为这本书就是讲这个方面的)。

  1. class X
  2. {
  3. public:
  4.     X(){...}  //构造函数
  5.     X(const X& x){...}  //拷贝构造函数
  6.     virtual ~X(){...}   //虚析构函数
  7.     virtual void foo(){...}  //虚函数foo
  8. ...
  9. };
  10. X foobar()  //一个全局函数foobar
  11. {
  12.    X xx;
  13.    X *px = new X;
  14.    
  15.    //foo() 是虚函数
  16.    xx.foo();
  17.    px->foo();
  18.    ...
  19.    delete px;
  20.    return xx;
  21. }
上面的函数foobar的函数体,经过编译之后的伪代码如下(注意,是伪代码,因为编译之后的代码是机器码了,这里用c伪代码来说明比较方便)

  1. //编译过后,foobar函数体的c++ 伪代码
  2. void foobar(X & _result)
  3. {
  4.    //对X xx;语句的转换
  5.    //因为最后返回的是xx,这里用了返回值优化,就是用_result来代替xx
  6.    _result.X::X();
  7.    
  8.    //对X *px = new X;这条语句的转换
  9.    px = _new( sizeof(X) );
  10.    if( 0 != px )
  11.       px->X::X();
  12.  
  13.    //对xx.foo()的转换
  14.    foo( &result);
  15.   
  16.    //对px->foo()语句的转换,其中_vtbl就是传说中的虚函数表
  17.    ( *px->_vtbl[2])(px);
  18.    
  19.    //对delete px的转换
  20.    if( 0 != px )
  21.    {
  22.       ( *px->_vtbl[1] )[px];
  23.       _delete( px );
  24.    }
  25.    
  26.    //对return xx的转换,返回值已经通过引用参数_result返回了。
  27.    return;
  28. }
其实,经过编译之后,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字节


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值