当我们需要设置class member的初值时,要么是经过member initialization list ,要么在construcotr内。


一、先讨论必须使用member initialization list的四种情况:

在以下四种情况,为了能够让程序被顺利编译,必须使用member initialization list:

  • 当初始化一个reference mmember时
  • 当初始化一个const member时
  • 当调用一个base class的constructor时,并且基类有一组参数
  • 当调用一个member class的constructor时,并且成员类也有一组参数

虽然在四种情况下,使用构造函数初始化成员,程序可以被正确编译并执行,但是效率不高,举例如下:

 class Word{
String _name;
int _cnt;
public:
//此时是在构造函数内执行数据成员的初始化
Word() { _name = ; _cnt = ;}
};

  上例对应四种情况的第四种,在这里Word constructor会先产生一个临时String object,然后将它初始化,之后以一个赋值运算符将临时性object指定给_name,然后再将那个临时String object摧毁(析构)。以下是编译器对Word constructor扩张的结果:

 //C++伪代码
Word::Word()
{
//调用Stringd的default constructor
_name.String::String(); //产生临时对象
String temp = String(); //memberwise的拷贝_name
_name.String::operator = (temp); //摧毁临时对象 temp
temp.String::~String(); _cnt = ; }

如果在成员初始值列表中进行成员初始化操作,明显更有效率,即如下所示:

 Word::Word: _name(){
_cnt = ; } //将会被扩展成下面形式:
Word::Word()
{
//调用String(int)构造函数
_name.String::String();
_cnt = ;
}

二、讨论下成员初始值列表中初始化的顺序:

  举个例子:   

Word::Word()
: _cnt(),_name() { }

对于上述构造函数,编译器会一一执行初始值列表,以适当顺序(这个顺序是由class中member的声明顺序决定的,而不是initialization list的顺序决定的)在构造函数内安插初始化操作。编译器在constructor的扩展如下:

 Word::Word ()
{
_name.String::String();
_cnt = ;
}

由初始化顺序可能会导致一个意想不到的错误:如下所示:

 class X{
int i;
int j;
public:
X(int val)
:j(val),i(j) {} };

在上述代码中,初始化的顺序应该是先初始i,因为i声明在前,但是因为j一开始没有初值,所以i(j)的结果会导致i无法预知其值。

所以我们可以将i的初始化操作放在构造函数内部,此时initialization list的执行顺序一定在explicit user code之前。如下所示:

X::X(int val)
: j(val) { i = j;}

 三、再来讨论其他两个关于初始化位置的问题:

  其一是、当调用一个成员函数来初始化一个成员的值时,但是请使用构造函数内的member,而不是member initialization list中的member,如下所示:

X::X(int val)
: i(xfoo(val)),j(val) {}

此时和此object相关的this指针,已经被构建妥当,编译器将constructor扩张为如下形式:

 X::X ()
{
i = this->xfoo(val);
j = val;
}

另一情况是还是不要使用派生类的成员函数作为基类构造函数的参数了。不太好

深度探索C++对象模型之第二章:构造函数语意学之成员初始值列表的更多相关文章

  1. 《深度探索C++对象模型》第二章 | 构造函数语意学

    默认构造函数的构建操作 默认构造函数在需要的时候被编译器合成出来.这里"在需要的时候"指的是编译器需要的时候. 带有默认构造函数的成员对象 如果一个类没有任何构造函数,但是它包含一 ...

  2. 深度探索C++对象模型之第二章:构造函数语意学之Copy constructor的构造操作

    C++ Standard将copy constructor分为trivial 和nontrivial两种:只有nontrivial的实例才会被合成于程序之中.决定一个copy constructor是 ...

  3. 深度探索C++对象模型之第二章:构造函数语意学之Default constructor的构造操作

    C++新手一般由两个常见的误解: 如果任何class没有定义默认构造函数(default constructor),编译器就会合成一个来. 编译器合成的的default constructor会显示的 ...

  4. 【C++对象模型】第二章 构造函数语意学

    1.Default Constructor 当编译器需要的时候,default constructor会被合成出来,只执行编译器所需要的任务(将members适当初始化). 1.1  带有 Defau ...

  5. 深度探索C++对象模型之第一章:关于对象之C++对象模型

    一.C和C++对比: C语言的Point3d: 数据成员定义在结构体之内,存在一组各个以功能为导向的函数中,共同处理外部的数据. typedef struct point3d { float x; f ...

  6. 深度探索C++对象模型之第一章:关于对象之对象的差异

    一.三种程序设计范式: C++程序设计模型支持三种程序设计范式(programming paradiams). 程序模型(procedural model) char boy[] = "cc ...

  7. 《深度探索C++对象模型》第一章 | 关于对象

    C++对象模式 非静态数据成员放置在每个类对象内,静态数据成员则被放置在所有类对象之外.静态和非静态的成员函数也被放置在所有类对象之外.每个类产生一堆指向虚函数的指针,放在虚表(vtbl)中.每个类对 ...

  8. 深度探索C++对象模型第四章:函数语义学

    C++有三种类型的成员函数:static/nonstatic/virtual 一.成员的各种调用方式 C with class 只支持非静态成员函数(Nonstatic member function ...

  9. 深度探索C++对象模型之第一章:关于对象之关键词所引起的差异

    ————如果不是为了努力维护与C之间的兼容性,C++远比现在简单的多. 如果一个程序员渴望学习C++,但是他却发现书中没有熟悉的struct,一定会苦恼,将这个主题包含到C++里,可以提供语言转移时的 ...

随机推荐

  1. 高级UI晋升之常用View(三)中篇

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从ViewPager来介绍常用View:文章目录 一.简介 二.基本使用 ...

  2. 使ie6/7/8支持css3的方法

    使用PIE.htc让IE6\7\8支持CSS3部分属性 包括圆角,阴影,背景渐变等效果 下载地址 http://css3pie.com/download/ 需要注意几点的是 第一,pie是以相对页面h ...

  3. echart 柱状图背景色设置

    方法一: series: [ { name: '1', type: 'bar', itemStyle: {//柱图背景色 color: '#111' }, data: list }, { name: ...

  4. Shell [[]]详解:检测某个条件是否成立

    [[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立. test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好:test 做不到的,[[ ]] 还能 ...

  5. leetcood学习笔记-235-二叉搜索树的最近公共祖先

    题目描述: 利用二叉搜索树的特点,如果p.q的值都小于root,说明p q 肯定在root的左子树中:如果p q都大于root,说明肯定在root的右子树中,如果一个在左一个在右 则说明此时的root ...

  6. Kotlin Download

    { https://github.com/JetBrains/kotlin/releases/tag/v1.3.50 }

  7. Unity 调用android

    { https://www.bilibili.com/video/av49002527 }

  8. alert样式优化

    //alert样式优化 function alert(msg, mode) { //mode为空,即只有一个确认按钮,mode为1时有确认和取消两个按钮 msg = msg || ''; mode = ...

  9. NX二次开发-NX+VS写代码设断点调试技巧

    在做NX二次开发的时候写完代码,编译可以通过,但是执行的时候却没有反应,或者得到的结果不对,说明肯定有地方传值出错了.我在查找代码错误的时候有几种方法:1.uc1601打印函数输入和输出的值看对不对. ...

  10. Mac 精品软件

    Snagit:Mac 平台下最优秀的屏幕截图软件,可以录制屏幕视频.截图以及对截图进行加工. Flux 4:强大易用的网页设计工具,不需要学习编程即可在一天内建成一个专业的网站 Jump Deskto ...