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 构造函数语意学相关推荐

  1. 深度探索C++对象模型第2章 构造函数语义学

    默认构造函数 两个误区: 1 任何class如果没有定义默认构造函数,就会被合成一个出来:只有在某些情况下被合成 2 编译器合成出来的默认构造函数会明确设定class中每一个数据成员的默认值 :默认值 ...

  2. 《深度探索C++对象模型》读书笔记第五章:构造析构拷贝语意学

    <深度探索C++对象模型>读书笔记第五章:构造析构拷贝语意学 对于abstract base class(抽象基类),class中的data member应该被初始化,并且只在constr ...

  3. 《深度探索C++对象模型》--5 构造析构拷贝 6 执行期语意学

     <深度探索C++对象模型>--5构造.析构.拷贝语意学 1.纯虚函数: (1)C++可以定义和调用一个纯虚函数,不过只可以静态调用,不可以由虚拟机制调用. 注意:pure virtu ...

  4. 深度探索C++ 对象模型(3)-默认构造函数Default Constructor

    1. Default Constructor只对base class subobjects和member class objects初始化,对data member不做操作 2. 编译器构造Defau ...

  5. 第2章构造函数语义学读书笔记——深度探索c++对象模型

    深度探索c++对象模型 第2章 构造函数语义学 2.1 Default Constructor的构建操作 2.2 Copy Constructor的构造操作 2.3 程序转化语义学 2.4 成员的初始 ...

  6. 深度探索C++ 对象模型(3)-默认构造函数Default Constructor续

    (1)带有虚函数的类 class Widget { public: virtual int flip() = 0;//..}; void flip(const Widget* widget ) { w ...

  7. 深度探索C++ 对象模型(4)-Default Copy Constructor(3)

    程序转化语意学 1. 显式初始化 原代码为: X x0; void foo_bar() { X x1(x0);X x2 = x0; X x3 = X(x0);} 编译器将产生拷贝构造函数,调用拷贝构造 ...

  8. 《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

    来源:http://dsqiu.iteye.com/blog/1669614 之前一直对C++内部的原理的完全空白,然后找到<Inside The C++ Object Model>这本书 ...

  9. [读书笔记]《深度探索C++对象模型》

    文章目录 前言 思维导图 第一章 关于对象 第二章 构造函数语意学 构造函数 拷贝构造函数 初始化列表 第三章 Data 语意学 第四章 Function 语意学 非静态成员函数 静态成员函数 虚成员 ...

  10. 深度探索C++ 对象模型(5)-Initialization list(3)

    四点: 1.list中的项目次序是由class中的members声明次序决定,不是由initialization list中的的代码决定 如下代码有一个陷阱,i值为一个不可预知未初始化的值.原因是按照 ...

最新文章

  1. 中国工程院《全球工程前沿2020》报告在京发布
  2. 更改Linux用户的登录shell环境
  3. python用turtle库绘制树图形_使用Python中的Turtle库绘制简单的图形
  4. vue人力管理_Vue管理后台框架选择推荐(收藏)
  5. C++Primer学习笔记:第1章 开始
  6. 让VS2010添加新类时自动添加public关键字(来自dudu博文)
  7. 一个银行客户经理的“变形记”
  8. linux下tomcat ssl证书,Tomcat部署ssl证书(Linux)
  9. 《企业软件交付:敏捷与高效管理精要》——2.2 MyCo公司和MyProj企业软件交付项目...
  10. microbit与python编程_简单5步开始学习microbit编程-windows篇
  11. 【SQL篇章--CREATE TABLE】
  12. 继承中的盲点,成员或者析构函数,成员函数中为什么有时候需要定义,有时候不需要呢,(已解决)...
  13. matlab线性同余发生器,线性同余法生成伪随机数
  14. 电工与电子技术基础【3】
  15. D. Count GCD
  16. Windows7/8/10系统中Altera USB-Blaster驱动安装的终极解决办法
  17. deepin20 外接显示器,标题栏美化
  18. 安岷老师 精益生产管理专家
  19. 百度地图获取经纬度后,获取区域代码和地址
  20. python获取时间戳算法_Python 获取时间,时间戳,时间差

热门文章

  1. Python看程序执行时间(time模块)
  2. solr调用lucene底层实现倒排索引源码解析
  3. Reactor by Example--转
  4. tomcat源码分析(一)初始化---Debug方式
  5. 【风控场景】互利网上数字金融典型场景: 网络营销
  6. 我爱我家 CIO 刘东颖:如何靠六大维度提升“数字化”能力?|鲸犀峰会
  7. 副业,程序猿的第二职业,聊聊我是怎么做的
  8. 基于Java语言构建区块链(四)—— 交易(UTXO)
  9. 以太坊发token教程
  10. ThoughtWorks技术专家详解:企业级区块链原来是这么玩的