条款04:确定对象使用前已被初始化

C part of C++ 不保证发生初始化; array
non-C part of C++ 发生初始化; vector
最佳处理办法:永远在使用对象之前先将它初始化。

内置类型:手工初始化。
非内置类型:确保每一个构造函数都将对象的每一个成员初始化。

初始化不等于赋值
C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。内置类型不一定有初始化动作。

对比赋值操作与使用初始化列表进行初始化
//先调用default构造函数,然后再调用copy 赋值操作符
A::A(const std::string& name)
{
	theName = name;
}
//只调用成员变量的copy构造函数
A::A(const std::string& name):theName(name)
{}

后一种方法高效得多。

PS:

  • 内置对象初始化和赋值的成本相同;
  • 如果成员变量属于内置类型,且成员变量为const或references,它们就一定需要初值,不能被赋值;
成员初始化次序

基类早于派生类;
成员变量以声明次序被初始化;

不同编译单元内的non-local static对象的初始化次序

C++对定义于不同编译单元内的non-local static对象的初始化次序并无明确定义。

class FileSystem{
public:
	...
	std::size_t numDisks() const;
	...
};
extern FileSystem tfs;    //non-local static 对象
class Dir{
public:
	Dir(params);
	...
};
Dir::Dir(params){
	...
	std::size_t disks = tfs.numDisks();  //使用tfs对象
	...
}
Dir temDir(params);  //为临时文件而做出的目录

temDir的构造函数可能会用到尚未初始化的tfs。
无法确定初始化次序。

解决办法:
将每个non-local static 对象搬到自己的专属函数内(该对象在此函数内被声明为static)。这些函数返回一个reference指向它所包含的对象。然后用户调用这些函数,而不是直接调用这些对象。
换句话说,non-local static对象被local static对象替换了。(sigleton模式的常见实现手法)

附加好处:

  • 绝佳的inline候选人,尤其在它们被频繁调用的时候;
  • 不调用该“仿真函数”,就绝不会引发构造和析构成本;

改动后的程序:

class FileSystem{
public:
	...
	std::size_t numDisks() const;
	...
};
//extern FileSystem tfs;    //non-local static 对象
FileSystem& tfs(){
	static FileSystem fs;
	return fs;
}
class Dir{
public:
	Dir(params);
	...
};
Dir::Dir(params){
	...
	//std::size_t disks = tfs.numDisks();  //使用tfs对象
	std::size_t disks = tfs().numDisks();  //改为tfs()
	...
}
//Dir temDir(params);  //为临时文件而做出的目录
Dir& temDir(params){
	static Dir dir;
	return dir;
}
总结:
  • 为内置型对象进行手工初始化,因为C++不保证初始化它们;
  • 构造函数最好使用初始化列表,而不要在构造函数本体内使用赋值操作。初始化列表列出的成员变量,其排列次序应该和它们在class中的声明次序相同;
  • 为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static对象;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值