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

  • 为内置类型对象手工初始化,因为C++不保证初始化他们

  • 构造函数最好使用构造函数初始值列表,而不要在构造函数体内使用赋值操作,初值列列出的成员变量其次序应该与类中声明次序相同

  • 为了免除‘’跨编译单元之初始化次序‘’问题,请以local static对象替换non-local static对象

    读取未初始化值会导致不明确行为:

int x;

在不同位置会出现不同行为,对于内置类型来说,如果在全局作用域声明,则默认初始化为0(对于int),但是如果是在局部作用域,其值是不确定的,未初始化的。对于类对象来说,其行为与其默认构造函数相关,但总的来说,最好在使用对象之前先把他初始化,确保每一个构造函数将对象的每一个成员变量都初始化


剩下重要的是区分赋值与初始化:
举例:考虑一个用来表示通讯录的类
.h文件中

class PhoneNuber{...};
//
class ABEntry{  //ABEntry="address book entry"
public:
	ABEntry(const std::string&name,const std::string&address,const std::list<PhoneNuber>&phones);
private:
std::string theName;
std::string theAddress;
std::list<PhoneNuber> thePhones;
int numTimesConsulted;
}

.cpp文件中:

ABEntry::ABEntry(const std::string&name,const std::string&address,const std::list<PhoneNuber>&phones)
{
	theName=name;       //这些都是赋值
	theAddress=address; //而不是初始化
	thePhones=phones;
	numTimesConsulted=o;
}

以上列子是会导致赋值的,赋值的成本是先调用default构造函数为成员变量设初值,然后再立刻赋予新值;C++规定是,对象的成员变量初始化动作发生在进入构造函数体之前;
再看member initialization list(成员列表初始值):

ABEntry::ABEntry(const std::string&name,const std::string&address,const std::list<PhoneNuber>&phones)
:theName(name),   //这些都是初始化了
theAddress(address),
thePhones(phones),
numTimesConsulted(0)
{}               // 构造函数本体不需要有任何动作

这个列表初始化与前面赋值那个结果相同,但是效率更高,不需要调用default构造函数了,直接利用各个实参为成员变量调用一次copy构造设定初值;


现在这一条款中就剩下不同编译单元内定义的non-local static对象的初始化次序问题了。

所谓编译单元,是指产出单一目标文件的那些源码,基本上是单一源码文件加上其所含入的头文件(#include files)。

当对于多个编译单元,并且每一个都至少包含一个non-local static 对象时(也就是位于global或者namespace作用域内 ,亦或在class内这file作用域内声明为static),真正的问题是,当一个编译单元内的某个non-local static对象的初始化使用了另一个编译单元内的某个non-local static对象,而他用到的这个对象可能还没有被初始化;这是因为C++对“定义于不同编译单元的non-local static对象”的初始化顺序并没有明确定义(给coder增加负担。。。)列子见effecttive C++ P30;

解决方法是Singleton模式的一种常见实现手法(首先说明此方法可行的原因是:C++保证,函数内的local static对象会在该函数被调用期间,首次遇上该对象定义式时被初始化;所以如果用函数调用返回一个reference指向local static对象,替换掉直接访问non-local static)

//Singl
class FileSystem{...};
FileSystem & instance()
{
	static FileSystem fs;
	return fs;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值