《深度探索C++对象模型》--2 构造函数语意学
来源:互联网 发布:重度抑郁症的表现知乎 编辑:程序博客网 时间:2024/05/22 17:25
1、default constructor的构造操作
C++standard:对于class X,如果没有任何user-declared constructor,那么会有一个default constructor 被暗中(implicitly)声明出来,一个被暗中声明出来的default constructor将是一个trivial constructor。但是这个生成的defaultconstructor只能满足编译器的需要,而不是程序的需要,所有的nonstaticdata member都不会被初始化,要注意。
一个nontrivialdefault constructor在ARM的术语中就是编译器所需要的那种,必要的话会由编译器合成出来。下面讨论nontrivial defaultconstructor的四种情况。
(1)带有defaultconstructor的memberclass object:如果一个类没有任何constructor,但它内含一个memberobject,而后者有defaultconstructor,那么这个class的implicitdefault constructor就是”nontrivial“的。
既然编译器会合成默认构造函数,那么在C++各个不同的编译模块中,编译器如何避免合成出多个默认构造函数(比如一个是a.c文件,另一个是b.c文件)呢?解决办法是吧合成的default constructor、copyconstructor、destructor、assignmentcopy operator都以inline方式完成,一个inline函数有静态链接,不会被文件以外看到。如果函数太复杂,不适合做成inline,就会合成出一个explicitnon-inline static实体。
如果class内含一个以上的memberclass objects,那么此class的每一个constructor必须调用每一个memberclass的defaultconstructor。编译器会扩张已经存在的constructor,在其中安插一些代码,似的user code被执行之前,先调用必要的defaultconstructor,且以声明顺序调用。
(2)带有DefaultConstructor的BaseClass:如果一个没有任何constructor的class派生自一个带有defaultconstructor的base class,那么这个derivedclass的defaultconstructor会被视为nontrivial,并因此需要被合成出来。
(3)带有一个VirtualFunction的Class:两种情况
(a)class声明(或继承)一个virtual function
(b) class派生自一个继承串链,其中有一个或更多的virtual base classes
有两个扩张会在编译期间发生:一个virtualfunction table会被编译器产生出来,内放class的virtualfunctions地址;在每一个classobject中,一个额外的pointer member会被编译器合成出来,内含相关的class vtbl的地址。
(4)带有一个VIrtualBase Class的Class: VirtualBase Class的实现法在不同的编译器之间有极大差异,然而,每一种实现法必须使virtualbase class在每一个derivedclass object中的位置,能够于执行期准备妥当。
2、Copy Constructor的构建操作
(1)当classobject以相同class的另一个object作为初值时,其内部是以所谓的default memberwise(按成员)initialization手法完成的。
(2)如果class没有声明一个copyconstructor,就会有隐含的声明或隐含的定义出现,C++standard把copyconstructor区分为trivial何nontrivial两种,只有nontrivial的实体才会被合成于程序之中。决定一个copy constructor是否为trivial的标准在于class是否展现出所谓的”bitwisecopy semantics“。
(3)BitwiseCopy Semantics(逐位拷贝)
不要BitwiseCopy Semantics的情况有四种:
(a)当class内含一个memberobject而后者的class声明有一个copyconstructor时(不论是被class设计者明确地声明,还是被编译器合成);
(b)当class继承自一个baseclass而后者存在一个copyconstructor时(不论是被明确声明还是被合成而得);
(c)当class声明了一个或多个virtualfunctions时;
(d)当class派生自一个继承串链,其中有一个或多个virtual base class时。
前两种情况,编译器需将member或baseclass的copyconstructor调用操作安插到被合成的copyconstructor中,情况3和4有点复杂。
重新设定VirtualTable的指针:增加一个virtualfunction table(vtbl),内含每一个有作用的virtual function地址;将一个指向vtbl的指针(vptr),安插在每一个classobject内。
处理VirtualBase Class Subobject:一个classobject以另一个object作为初值,而后者有一个virtual base class subobject,也会使bitwisecopy semantics失效。
3、程序转化语意学
(1)返回值的初始化
已知函数定义:
X bar()
{
X xx;
//...
return xx;
}
bar()返回值如何从局部对象拷贝?
Stroustrup在cfront的解决方法是一个双阶段转化:
加上一个额外参数,类型是reference
在return前安插一个copy constructor操作
//函数转化
void bar(X& _result)//加上一个额外参数
{
X xx;
xx.X::X();//编译器产生的default constructor调用操作
//....处理xx
_result.X::XX(xx);//编译器产生的copyconstructor调用
return;
}
一个bar()调用被转化为:
X xx = bar();
转为:
X xx;
bar(xx);//注意不必调用default constructor
(2)在编译器层面做优化
以_result参数取代namedreturn value,称为NamedReturn Value(NRV)优化。由于NRV需要调用默认拷贝构造,如果编译器不生成,则需要手动添加拷贝构造。
(3)拷贝构造要还是不要?
如果class需要大量的memberwise初始化操作,例如以传值的方式传回value,则提供一个explicit copy constructor inline会更有效率。
4、成员的初始化队伍
必须使用member initialization list的情况:初始化一个reference member时;初始化const member;调用base class的constructor,而它拥有一组参数;调用member class的constructor,而它拥有一组参数。
使用成员初始化列表,可以提高效率,因为initializationlist的项目被放于explicituser code之前,但是要注意如果初始化某一项依赖于另一项时初始化的顺序,好的方法是将依赖某一项的成员放于constructor体内。
- 深度探索C++对象模型 2构造函数语意学
- 《深度探索C++对象模型》--2 构造函数语意学
- 深度探索C++对象模型 之 构造函数语意学
- 第2章 构造函数语意学-《深度探索C++对象模型》读书笔记
- 《深度探索C++对象模型》- 第2章 构造函数语意学
- 【深度探索C++对象模型读书笔记】【第2章】构造函数语意学
- 《深度探索C++对象模型》读书笔记之构造函数语意学
- 深度探索C++对象模型学习 之 C++构造函数语意学(一)
- 【深度探索C++对象模型】第二章 构造函数语意学(上)
- 【深度探索C++对象模型】第二章 构造函数语意学(中)
- 《深度探索C++对象模型》读书笔记之构造函数语意学
- 《深度探索C++对象模型》—构造函数语意学(The Semantics of constructors)
- 《深度探索C++对象模型》读书笔记第二章:构造函数语意学
- 《深度探索C++对象模型》第二章 构造函数语意学
- 【C++】深度探索C++对象模型之构造、析构、拷贝语意学
- 【C++】深度探索C++对象模型之Function语意学
- 深度探索C++对象模型-语意学
- 《深度学习C++对象模型》学习笔记2:构造函数语意学
- Around the World in Eighty Days 19/201
- 设计模式(23)——访问者模式与双分派
- poj 2709 Painter
- POJ 3352 Road Construction / 边双连通分量
- HDU Eddy's digital Roots
- 《深度探索C++对象模型》--2 构造函数语意学
- 设计模式23种小结
- Linux学习路线之linux的amr开发学习方法
- maven学习笔记【配置参考】
- 高斯消元法
- 5.3 与其他Fragment交互
- 【VS2010学习笔记】【函数学习】二(SetTimer()函数)
- DOM知识
- Hibernate配置文件hbm主键的generator可选项