深度探索C++对象模型:成员变量的初始化列表

本文详细解析了C++中构造函数初始化列表(initialization list)的使用场景和效率优势,尤其是在初始化引用成员、常量成员、基类构造函数及具有一组参数的成员对象时的必要性。同时,通过对比传统初始化方式,阐述了初始化列表如何避免不必要的临时对象创建,提高程序运行效率。
摘要由CSDN通过智能技术生成

对 class members 的初始化操作可以放在 member initialization list 或者 construct 中进行,但两者之间是有一些区别的,无论是在效率上还是在语法上。

何时应该使用 initialization list ?
在语法方面来说,为了程序可以通过编译,下面几种情况必须使用 initialization list :

当初始化一个 reference member 时
当初始化一个 const member 时
当调用一个 base class 的 constructor ,并且它拥有一组参数时
当调用一个 member object 的 constructor ,并且它拥有一组参数时

下面来看一下在效率方面什么时候应该用 initialization list 。首先看下面一段代码:

class Word {
public:
  Word() {
    _name = 0;
    _cnt = 0;
  }
protected:
  String _name;
  int _cnt;
}

上面这段代码没有语法错误,程序可以正确的编译执行,但是效率上却不尽人意。首先我们来看编译都干了什么,下面是经过编译器扩展后的 constructor 伪码:

// C++ 伪码
Word::Word {
  // 调用 _name 的默认构造函数
  _name.String::String();
  // 生成临时对象
  String temp = String(0);
  // 将临时对象 memberwise 拷贝给 _name
  _name.String::Operator=(temp);
  // 销毁临时对象
  temp.String::~String();
  _cnt = 0;
}

通过编译器扩展后的代码我们可以看到,这种方式的 _name 初始化效率很差,需要产生一个临时对象,多了一次构造、一次拷贝、一次析构的额外操作。不过通过这种初始化方式对 _cnt 并没有什么影响。所以改进后的代码应该是这样的:

Word::Word() : _name(0) {
  _cnt = 0;
}
经过编译器扩展后的伪码类似这样:

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

member initialization list 到底都做了什么?
通过上面的分析,可以大概看出 initialization list 的作用,具体细节是:

编译器会一一操作 initialization list ,以适当的次序在 constructor 之内安插初始化操作,并且在任何 explicit user code 之前。

member initialization list 存在的一些风险
上面所说的 适当次序 是指 members 在 class 里的声明次序,而不是在 initialization list 的排列次序,所以例如下面这段代码就会问题:

Class X {
  int i;
  int j;

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

上面代码的本意是先用 val 初始化 j 在用 j 初始化 i ,但实际上 initialization list 的初始化次序是按照 members 在 class 里的声明次序,所以会先初始化 i ,然后才是 j ,而 j 一开始并未进行初始化,导致 i(j) 的结果也无法预料。

其实做为一个学习者,有一个学习的氛围跟一个交流圈子特别重要这里我推荐一个C/C++基础交流583650410,不管你是小白还是转行人士欢迎入驻,大家一起交流成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值