`
daojin
  • 浏览: 676307 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

深入探索C++对象模型学习笔记2

 
阅读更多

密码管理请下载:

http://a.app.qq.com/o/simple.jsp?pkgname=com.wa505.kf.epassword

 

1.   关于对象

1.1.  虚表:

1.1.1.       每一个class在编译时期产生一堆指向Virtual函数的指针. 并且放在表格中.[由于虚表定义在与类有关的静态数据区域,因此,一定是在编译时期完成].与此同时,classRTTI也放入了第一个slot.

 

1.2.  指向虚表的指针:

1.2.1.       每一个ClassObject被添加一个指针vptr.这个指针在运行时(构造函数,copy构造函数, 赋值运算符), 被指向对应的虚表, 当然了,这个虚表也包含RTTI信息.

1.3.  C++以以下方法支持多态.

1.3.1.       将一个子类指通过赋值操作符,  转换为父类指针.

1.3.2.       通过虚函数机制.

1.3.3.       通过dynamic_cast typeid运算符。

2.   构造函数语义学

2.1.    Default Constructor的建构操作

2.1.1.       带有Default ConstructorMember Class Object

2.1.2.       带有Default ConstructorBase Class

2.1.3.       带有Virtual Function cass

2.1.4.       带有一个Virtual Base Class class

2.2.   Copy Constructor的建构操作

2.2.1.       Bitwise Copy Semantics

2.2.2.       不要Bitwise Copy Semantics!的四种情况与 Default Constructor类似。

2.2.3.       重新设定Virtual Table(不能Bitwise Copy).

2.2.4.       重新处理Virtual Base Class Subobject. 因为在不同的同一继承层次的子类中,vbtr的值是不同的(不能Bitwise Copy).

2.3程序转换语意学Program Transformation Semantics

2.3.1          明确的初始化操作(Explicit Initialization)。重写定义,并明确调用copy构造

2.3.2          参数的初始化(隐式初始化)。除了初始化之外,还修改函数的签名。(老版本的BorlandC++没有修改)

2.3.3          返回值的初始化(Return Value Initialization.

改写函数签名,改为通过参数来返回。例如foo(A& a)

2.3.4          用者层面做优化(Optimization at the user Level使用者通过一些设计来优化代码。例如可以节约一次默认构造。

2.3.5          编译器优化:节约一次copy构造。但是有可能会破坏程序作者的意图,例如,如果基于copy构造做了一些事情,那么就可能会报错。对于直接返回一个值的函数。例如

A foo(){

A a; 

a.f();

return a};

首先改造为

Foo(A& a){

          a.A::A()

a.f()

a.A::A(a)

}

然后优化掉copy构造(C++标准是允许的)

Foo(A& a){

               a.A::A()

a.f()

}

2.3.6          Copy Constructor:要还是不要?

当编译器提供NRV优化时,最好还是提供一个。这样在大量的基于成员的初始化memberwise(与Bitwise相对)时,可以激活NRV

2.4成员们的初始化队伍(Member Initialization List

2.4.1          初始化一个reference member

2.4.2          初始化一个constmember

2.4.3          BaseClass 的构造函数没有默认构造时,需要一组参数。

2.4.4          MemberClass的构造函数没有默认构造时,需要一组参数

2.4.5           另外,初始化的次序由member的生命次序决定,不是由,初始化列表中的次序决定。最好避免在初始化列表中,用一个member为另外一个member设定初值。如果以member来初始化baseclass,那么问题将会更加严重。

Member Initialization List的执行顺序可能会因为插入新的代码而打乱。如果以member来初始化baseclass,或者memberclass

 

 

3.   Data语意学(The Semantics of Data

1.       DataMember的绑定, inline函数延迟绑定类成员与全局变量的绑定顺序。

特殊的typedef,经过VC++验证,不会使用延迟绑定(与深度探索这本书有出入)。

2.       Datamember的布局:编译器加入一些字段vptrvbtr等,字节对齐策略。

3.       字节对齐策略,VC++上为1.数据成员对齐规则:对齐方式n pragma pack(n)
1.     成员起始地址对齐:就是说变量存放的起始地址的偏移量:min(sizeof(类型),对齐方式n)或其倍数.

2.     整体对齐规则:结构的总大小也有个约束条件:
min(最大的sizeof(类型),对齐方式n)的倍数.

4.       继承与DataMember

继承,多态,多重继承,都不会产生效率问题。而虚拟继承,由于在编译阶段,不能通过指针类型直接判断对象的位置,因此必须采用间接法。会增加额外的调用负担。多态会增加一个vfptr,虚拟继承会增加一个vbptr,同时,虚拟继承也会使得Virtual Base Class的实体在整个继承体系中仅有一个。

5.       对象成员的效率。(虚拟继承下效率较差,其他相同)

在继承模型中,单一继承效率最高,一层的虚拟继承次之,而多层的虚拟继承效率最差。

6.       指向Members指针。

指向Member的指针实际上是,它所在的SubOjbect(相对与Object)中的offset位置。

7.       指向Members指针的效率。(虚拟继承下效率较差,其他相同)

与虚拟继承甚至继承体系都没有关系。但是,如果是虚拟继承,在访问点,与访问对象成员一样,只有在运行时才能决定Virtual Base Class Object的地址。因此通过访问指向Member的指针来访问Member,其效率与访问成员对象相同。

4.   Function语意学(The Semantics of Function

4.1   Member的各种调用方式

   非静态成员,signature函数原型的修改,增加对成员的访问语义,名称的特殊处理,

虚拟成员函数,通过vfptr在运行时调用。因为单凭借一个指针的值和类型,无法确定对象的vftable的地址。

静态成员函数,由于没有this指针,因此不能为虚函数,constvolatile。不需要经过class

Object 调用。不能访问nonstatic members

4.2   Virtual Member Functions

         不管是单一继承和多重继承,如果没有VirtualMemberFunctionVirtual Base Class,那么在编译期就能判断函数的位置。因此没有效率上的负担。

         单一继承时,如果有VirtualMemberFunction, 就会转换为一个间接的访问,因此会增加效率上的负担。Ptr->vptr[4](ptr)

多重继承时,效率问题发生在第二以及后继的带有Virutal Member Function的类上。由于在调用的时候通过thunk技术调整this指针,但是无法在编译阶段知道一个类是否是多重继承中的第二或者后继的基类,因此,必须在运行时,对此进行特殊处理。

虚拟继承下的虚拟函数Virutal Member Function

效率问题非常大,不但有可能要调整this指针,而且访问Virtual Base Class都需要延迟到运行时才可以。

效率排名:

Inline member>Nonmember friend=Static Member=NonStaticMember>virtual member>virtualmember(多重继承)&&VirtualMember(虚拟继承)> VirtualMember(虚拟继承+多重继承)

4.3   指向Member Function的指针:

       效率排名:

Nonmember = Member > NonVirtual(多重继承)> NonVirtual(虚拟继承)&&VirtualMember(单一继承)>多重继承 virtual &&虚拟继承virtual

       不同点在于多重继承,影响到了效率。由于需要对虚拟机制进行兼容性处理,增加了一些判断代码。其中的&&代表,未知

 

1
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics