当我们需要设置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. 剑指offer——58数组中数值和下标相等的元素

    题目三: 数组中数值和下标相等的元素. 假设一个单调递增的数组里的每个元素都是整数并且是唯一的.请编程实现一个函数,找出数组中任意一个数值等于其下标的元素.例如,在数组{-3,-1,1,3,5}中,数 ...

  2. 通过MyEclipse操作数据库,执行sql语句使我们不用切换多个工具,直接工作,方便快捷

    通过MyEclipse操作数据库,执行sql语句使我们不用切换多个工具,直接工作,方便快捷.效果如下:     步骤1:通过MyEclipse中的window->show View->ot ...

  3. script标签的defer、async属性

    之前一直对script标签的defer.async属性一知半解,直到看到了论坛上某大神发的图片,茅塞顿开!!!!!

  4. docker容器和宿主机时间不一致的问题

    第1种:复制宿主机的localtime文件,到容器里docker cp /etc/localtime threg:/etc/ 注:这里 threg为容器名称,复制完后需重启容器 第2种在构建docke ...

  5. 软工-五月心得体会 PB16110698

    伴随着愈发红润的骄阳,火热而紧张刺激的五月悄然而至.这一个月以来,曾经让同学们“废寝忘食”的软工课大作业终于告一段落,每周一篇的读书笔记也缓到半月一篇,着实令人长吐一口气.但这一份表面的余裕当然没有看 ...

  6. uboot刷机

    ath> tftp xx.zpk Trying eth0 Using eth0 device TFTP from server 192.168.1.104; our IP address is ...

  7. 【JZOJ6285】飘雪圣域

    description analysis 从求联通块出发根本没做法,于是考虑连通块里面的边 对于一个询问\([l,r]\),一条边的左端点\(≥l\)且右端点\(≤r\)才在这个区间的点之间 于是对于 ...

  8. 【转载】Visual Studio + VA 常用快捷键

    有过几年没怎么做window开发,发现回头再用VS忘记了好多快捷键,好记性真是不如烂笔头. 快捷键习惯设置:Tools->Options->Keyboard:Apply the follo ...

  9. lua执行的两种方式

    一.交互模式 二.脚本式 创建一个以lua结尾的文件,例如hello.lua文件内容 println("hello world")

  10. <转载>深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别

    C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字符数组和字符指针这两个 ...