ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:23.10KB ,
资源ID:13040432      下载积分:1 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-13040432.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(《深度探索C对象模型》读书笔记 二.docx)为本站会员(b****8)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

《深度探索C对象模型》读书笔记 二.docx

1、深度探索C 对象模型读书笔记 二深度探索C 对象模型读书笔记 二2002-7-6 3.3 Data Member的存取1.不管什么情况,每一个static data member只有一个实体,放在程序的data segment之中,每次程序取用static member,不管是通过operator:还是member selection operator,都会被内部转化为对该唯一extern实体的直接参考操作。每一个static member的存取以及与class的关联不会导致任何执行时间或空间上的额外负担。如果有两个classes,每一个都声明了一个static member freeList

2、,那么当它们都放在程序的data segment时,就会导致名称冲突,编译器的解决方法是使用name-mangling,暗中对每一个static data member编码,以获得一个独一无二的程序识别代码。2.有多少个编译器,就有多少种name-mangling做法,任何name-mangling做法都有两个要点:一种算法,推导出独一无二的名称;如果编译系统或者环境工具必须和使用者交谈,那些独一无二的名称可被轻易推导回原先的名称。3.取一个static data member的地址,会得到一个指向其数据类型的常量指针,而不是指向其class member的指针。4.nonstatic dat

3、a members直接放在每一个class object之中,除非经过显示的explicit或隐含的implicit class object,没有办法直接存取它们。只要程序员在一个member function中直接处理一个nonstatic data member,所谓implicit class object就会发生,其实质是编译器会为这个member function增添一个const this指针,而在函数体内通过这个this指针来存取nontatic data member。5.欲对一个nonstatic data member进行存取操作,编译器需要把class object的起

4、始地址加上data member的编译量offset,如地址&someObject.someMember等于&someobject+(&theClass:someMember 1);指向data member的指针,其offset值总是会被加上1,这样可以使编译系统区分出一个指向class第一个data member的指针和一个没有指向任何data member的指针。6.每一个nonstatic data member的偏移量在编译时期即可获知,甚至如果member属于一个单一或多重继承体系中base class subobject也是一样,因此其存取效率和一个C struct member

5、或一个nonderived class的member的存取效率是一样的。但是在虚拟继承的情况下就另当别论了:如果该nonstatic data member是一个virtual base class的member,并且通过指针来存取的话,在编译时期就不会得知这个member真正的offset位置,所以这个存取操作必须延迟至执行期,经由一个额外的间接导引才能够解决。2002-7-7 3.4继承与Data Member 1.在C+继承模型中,一个derived class object所表现出来的东西,是其自己的members加上其base classes members的总和。C+并未规定der

6、ived class members和base classes members的排列次序。不过,在大部分编译器上,除virtual base class外,base class members总是先出现。2.一般而言,具体继承concrete inheritance并不会增加空间或存取时间上的额外负担。3.把两个原本独立不相干的classes凑成一对type/subtype,并带有继承关系容易犯两个错误。一是可能会重复设计一些相同操作的函数,一般而言,选择某些函数做成inline函数,是设计class的一个重要课题;二是把一个class分解为多层,有可能会为了表现class体系之抽象化,因为编

7、译器的边界调整而膨胀所需空间。其根本原因是C+保证出现在derived class中的base class subobject有其完整原样性。4.C+最初问世时,许多编译器把vptr放在class object的尾端,这样可以保留base class Cstruct的对象布局。此后,某些编译器开始把vptr放在class object的开始处,这样会给多重继承下通过指向class members之指针调用virtual function带来一些帮助,否则,在执行期不仅必须备妥从class object起点处开始量起的offset,而且必须备妥class vptr之间的offset。5.单一继承

8、提供了一种自然多态的形态,是关于class体系中base type和derived type之间的转换。一般来说,base class和derived class objects都是从相同的地址开始。但若将vptr放在class object的起始处,如果base class没有virtual function而derived class有,那么单一继承的自然多态就会打破。此时,把一个derived object转换为其base类型就需要编译器的介入,用以调整地址。而在既是多重继承又是虚拟继承的情况下,编译器的介入则更有必要。6.多重继承的复杂度在于derived class和其上一个base

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

10、class内如果内含一个或多个virtual bass class subobjects,将被分割为两部分:一个不变局部和一个共享局部。不变局部总是拥有固定的offset,其数据用以指定共享局部的位置,可以直接存取;而共享局部表现的就是virtual base class subobject,其位置会因为每次的派生操作而变化,只可间接存取。各家编译器实现技术之间的差异就在于间接存取的方法不同。8.一般而言,virtual base class最有效的一种运用方式是:一个没有任何data member的抽象class。2002-7-14 3.5对象成员的效率如果没有把优化开关打开,就很难猜测一个

11、程序的效率表现,因为程序代码潜在性的受到某些与编译器有关的东西的影响。程序员如果关心效率,应该实际测试,不要光凭推论或常识判断或假设。优化操作并不一定总是能够有效运行。2002-7-15 3.6指向Data Members的指针指向data members的指针可用来详细调查class members的底层布局,可用来决定vptr是放在class的起始处还是尾端,还可用来决定class中access sections的次序。取一个nonstatic data member的地址,将会得到它在class的offset;而取一个static data member的地址或者取一个绑定于真正clas

12、s object身上的data member的地址,将会得到该member在内存中的真正地址。这也正是someType someClass:*和someTye*潜在的区别。2002-7-16 Function语意学The Semantics of Function C+支持三种类型的member functions:static、nonstatic和virtual,每一种类型的调用方式都不同。4.1 Members的各种调用方式1.C+的设计准则之一便是nonstatic member function至少必须和一般的nonmember function有着相同的效率。编译器内部会将membe

13、r函数实体转换为对等的nonmember函数实体,其步骤为:改写函数原型signature以安插一个额外的参数this到member function中,使得class object可以调用该函数。其中,this是const指针,若该函数为const,则反映在this上面的结果是this指向的data也为const;将每一个对nonstatic data member的存取操作改为经由this指针来存取;将member function重新写成一个外部函数,对函数名称进行mangling处理;此后,每一个函数调用操作也都必须转换,用以提供相应的实参。2.关于虚拟函数的内部转换步骤:若norma

14、lize是一个virtual member function,ptr-normalize();会被内部转化为(*ptr-vptrt)(ptr);事实上,vptr名称也会被mangled,因为可能存在有多个vptrs;t是vitrual table slot的索引值,关联到normalize函数;第二个ptr表示this指针。3.使用class scope operator明确调用一个vitual function,或经由一个class object调用一个vitual function其决议方式会和nontatic member function一样!故virtual function的一个i

15、nline函数实体可被扩展开来,因而提供极大的效率利益。4.static member function的主要特征是没有this指针,这导致它不能直接存取其class中的nonstatic members,不能被声明为const、volatile或virtual,也不需要经由class object才能调用。static member function会被提出于class声明之外,并给予一个经过mangled的适当名称。如果取一个static member function的地址,得到的将是其在内存中的地址,其地址类型并不是一个指向class member function的指针,而是一个no

16、nmember函数指针。static member function的一个意想不到的好处是可以成为一个callback函数,也可以成功地应用在thread函数身上。2002-07-17 4.2 Virtual Member Functions虚拟成员函数1.C+中,多态polymorphism表示以一个public base class指针或reference寻址出一个derived class object。识别一个class是否支持多态,唯一适当的方法试看它是否有任何virtual function。只要class拥有一个virtual function,它就需要一份额外的执行期型别判断信

17、息。2.一个class只会有一个virtual table,其中内含对应class object中所有的active virtual functions的函数实体的地址。这些active virtual functions包括:一个class定义的函数实体。它会改写overriding一个可能存在的base class virtual function。继承自base class的函数实体。此时该class不改写base class virtual function。一个pure_virtual_called()函数实体,它既可以扮演pure virtual function的空间保卫者,也可

18、以当作执行期异常处理函数。如果该函数被调用,通常的操作是结束程序。3.每一个virtual function都被指派一个固定不变的索引值,该值在整个继承体系中保持与特定virtual function的关联。这样就可以在编译时期设定virtual function的调用。2002-7-20 4.多重继承下,一个上层basse classes数目为n的derived class,它将内含n-1个额外的virtual tables。其主要实体与最左端的base class共享,其中包含所有virtual functios的地址;n-1个次要实体与其它base classes有关,其中只包含出现在对

19、应base class中virtual functions的地址。5.在多重继承中支持virtual function,其复杂度围绕在第二个及后继base class上,以及执行期this指针调整上。第二(或后继)base class会影响对virtual function支持的3种情况:通过指向第二个base class的指针,调用derived class virtual function;通过指向derived class的指针,调用第二个base class中一个继承而来的virtual function;允许virtual function函数的返回值类型有所变化,可能是base t

20、ype,也可能是publicly derived type。6.关于执行期this指针调整比较有效率的解决方法是thunk。所谓thunk是一小端assembly码,用来以适当的offset值来调整this指针并跳到相应的virtual function。thunk技术允许virtual table slot继续内含一个简单的指针,此时多重继承将不需要任何空间上的额外负担!slots中的地址可以直接指向virtual function,也可以指向一个相关的thunk。4.3函数的效能nonmember、static member和nonstatic member function在内部都会转化

21、为完全相同的形式,三者效率相同。2002-08-08 4.4指向Member Function的指针对一个nonstatic member function取址,得到的是该函数在内存中的地址;而面对一个virtual function,得到的将是一个索引值。这个值是不完整的,必须被绑定于一个class object上,才能够通过它调用函数。指向member function的指针的声明语法,以及指向member selection运算符的指针,其作用是作为this指针的空间保留者。因此,static member function的类型是函数指针,而不是指向member function的指针

22、。使用一个member function指针,如果并不用于virtual function、多重继承、virtual base class等情况的话,其成本并不比使用一个nonmember function指针要高。4.5 Inline Functions关键词inline只是一项请求。如果在某个层次上,函数的执行成本比一般的函数调用及返回机制所带来的负荷低,那么该请求被接受,编译器就用一个表达式合理地将函数扩展开来。真正的inline函数扩展操作是在函数调用的那一点上。在inline扩展期间,每一个形式参数会被对应的实际参数所取代,inline函数中的每一个局部变量都必须被放在函数调用的一个

23、封闭区段中,并拥有一个独一无二的名称。这会带来参数的求值操作以及临时性对象的管理。2002-08-11构造、解构、拷贝语意学Semantics of Construction,Destruction,and Copy 1.一般而言,class的data member应该被初始化,而且只在constructor中或其它member functions中初始化,其它任何操作都将破坏其封装性质,使其维护和修改更加困难。2.可以定义并调用invoke一个pure virtual function,但它只能被静态调用,不能经由虚拟机制调用。每一个derived class destructor会被编译器

24、加以扩展,静态调用每一个virtual base class以及上一层base class的destructor。因此,不管base class的virtual destructor是否声明为pure,它必须被定义。5.1无继承情况下的对象构造C+Standard要求编译器尽量延迟nontrivial members的实际合成操作,直到真正遇到其使用场所为止。5.2继承体系下的对象构造一般而言,继承体系下编译器对constructor所作的扩充操作以及次序大约如下:所有virtual base class constructors必须从左到右、从深到浅被调用:如果class被列于member

25、initialization list中,那么任何明确指定的参数都必须传递过去,否则如果class有一个default constructor,也应该调用它;class中的每一个virtual base class subobject的偏移量offset必须在执行期可被存取;如果class object是最底层most-derived的class,其constructors可能被调用,某些用以支持这个行为的机制必须被方进来。以base class的声明次序调用上一层base class constructors:如果base class被列于member initialization list

26、中,那么任何明确指定的参数都必须传递过去,否则若它有default constructor或default memberwise copy constructor,那么就调用它;如果base class是多重继承下的第二或后继的base class,那么this指针必须有所调整。如果class object有virtual table pointer(s),它(们)必须被设定初值,指向适当的virtual table(s)。如果有一个member没有出现在member initialization list中,但它有default constructor,调用之。将member initial

27、ization list中的data members的初始化操作以members的声明次序放进constructor的函数本身。2002-8-18 5.3对象复制语意学Object Copy Semantics 1.只有在默认行为所导致的语意不安全或者不正确以致发生别名化aliasing或者内存泄漏memory leak时,才需要设计一个copy assignment operator。否则,程序反倒会执行得较慢。2.如果仅仅是为了把NRV优化开关打开而提供一个copy constructor,那么就没有必要一定要提供一个copy assignment operator。3.copy assi

28、gnment operator有一个非正交情况,那就是它缺乏一个平行于member initialization list的member assignment list。调用base class的copy assignment operator示例:Point:operator=(p3d);或(*(Point*)this)=p3d;或(Point&)(*this)=p3d;4.事实上,copy assignment operator在虚拟继承情况下行为不佳,需要小心设计和说明。许多编译器甚至并不尝试取得正确的语意,它们在每一个中间的copy assignment operator中调用每一个b

29、ase class instance,于是造成virtual base copy assignment operator的多个实体被调用。建议尽可能不要允许一个virtual base class的拷贝操作,并不要在任何virtual base class中声明data member。5.5解构语意学Semantics of Destruction如果class没有定义destructor,那么只有在其内带的member object或base class拥有destructor时,编译器才会自动合成出一个destructor。一个由程序员定义的destructor被扩展的方式类似constr

30、uctors被扩展的方式,只是顺序相反:destructor的函数本体首先被执行;如果class拥有member class objects,而后者拥有destructors,那么它们将以声明的相反顺序而调用;如果object内带一个vptr,则现在被重新设定以指向适当base class之virtual table;如果有任何直接的nonvirtual base classes拥有destructor,它们将以声明的相反顺序而调用;如果有任何virtual base classes拥有destructor,而前面讨论的这个class是most-derived class,那么它们会以原先构造

31、顺序的相反顺序被调用。2002-8-19执行期语意学Runtime Semantics 6.1对象的构造和解构1.一般而言,constructor和destructor的安插都如你所预期。但如果一个区段或函数中有一个以上的离开点,情况就会复杂一些,destructor会放在每一个离开点之前。通常,我们要求将object尽可能放在使用它的那个程序区附近,这样做可以节省不必要的对象产生和销毁操作。2.C+程序中所有的global objects都被放置在程序的data segment中,如果不明确指定初值,object所配置的内存内容将为0(C并不自动设定初值)。如果global object有c

32、onstructor和destructor的话,我们说它需要静态的初始化和内存释放操作。2002-8-20 3.virtual base class的subobject在每个derived class中的位置可能会变动,不能在编译时期确定。以一个derived class的pointer或reference来存取virtual base class subobject,是一种nonconstant expression,必须在执行期方可评估求值。4.使用静态初始化的object有一些缺点。其一,无法放入try区段,任何throw操作必将触发exception handling library的默认函数terminate();其二,程序员必须为控制需要跨越模块做静态初始化objects的依赖顺序而产生的复杂度付出代价。建议根本就不要使用那些需要静态初始化的global objects。5.新的C+标准要求编译单位中的static local class objects必须在相应函数第一次被调用时才被构造,而且必须以相反的次序销毁。由于这些objects是在需要时才被

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2