当我们需要设置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. 关于 CShellManager 的作用

    也许大家看到这个题目,未曾进行windows shell编程的同学呢,会不明白是什么意思,这里简单的介绍一下,windows shell就是可以使编写的程序与系统关联(如快捷方式,托盘图标等),管理系 ...

  2. EM相关两个算法 k-mean算法和混合高斯模型

    转自http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006924.html http://www.cnblogs.com/jerrylead/ ...

  3. 54-Ubuntu-打包压缩-4-bzip2压缩和解压缩介绍

    bzip2 tar和bizp2命令结合可以实现文件打包和压缩 tar只负责打包,但不压缩 用bzip2压缩tar打包后的文件,其扩展名一般为xxx.tar.bz2 在tar命令有一个选项-j可以调用b ...

  4. LCA的RMQ求法

    参考博客 仔细想一想:最近的公共祖先,其实,搜索时回朔,连通这两点,那深度最低肯定是最近的公共祖先啊. 那这样就可以变成RMQ问题了. #include<stdio.h> #include ...

  5. 怎样在Cocos2d-x中使用Lua脚本

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013321328/article/details/25699545 笔者使用的是Cocos2d-x ...

  6. GP下CalculateField的用法

    以前用过这个类做字段计算,许久不用有些忘却,记录一下使用方式 public static void CalculateField(IFeatureLayer featureLayer,IField f ...

  7. Linux (raspberry) 安装 telnet server

    可能由于内核或者版本问题 ,网上的telnet服务器安装教程,总是无法安装成功 ,下面说说基于debian发行版(树莓派)telnet 服务器端的安装,便于以后的远程访问. 具体可以通过netstat ...

  8. linux 挂载iso文件,挂载ntfs文件系统

    映像档不可录就挂载使用.通过loop命令来执行 好吧.跟同事要了一个win10系统盘.插入,竟然是灰色的. ,一点击,提示无法挂载,仔细看了一下下面的内容,原来不支持ntfs格式,好吧,win10系统 ...

  9. HTML——列表标签

    什么是列表? 把…制成表,以表显示. 容器里面装载着文字或图表的一种形式,叫列表. 列表最大的特点就是 整齐 .整洁. 有序. 无序列表 ul (重点) 无序列表的各个列表项之间没有顺序级别之分,是并 ...

  10. 《DNS攻击防范科普系列2》 -DNS服务器怎么防DDoS攻击

    在上个系列<你的DNS服务真的安全么?>里我们介绍了DNS服务器常见的攻击场景,看完后,你是否对ddos攻击忧心重重?本节我们来告诉你,怎么破局!! 首先回顾一下DDoS攻击的原理.DDo ...