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

一、内置类型必须手工初始化

   因为读取未初始化的值会导致不明确的行为。在C++里的C语言部分中,对象的初始化没有保证;但对于其他部分,却有此保证。
  对于这种情况,最好的办法就是:永远在使用对象前,手工去先将其初始化

二、内置类型以外的初始化依靠于其构造函数

   这里有一个规则:必须确保每个构造函数中,都将对象中的每一个成员初始化
   但别混淆了赋值和初始化,最好是使用成员初值列替换赋值动作
   结合下面的例子理解:

class Player 
{
public:
	Player(const string& name, const int& level);

private:
	string theName;
	int theLevel;
};
//下面是赋值
Player::Player(const string& name, const int& level)
{
	theName = name;
	theLevel = level;
}
//下面是成员初值列
Player::Player(const string& name, const int& level)
  :theName(name),
   theLevel(level)
{ }

   上面第一个实现的就是赋值动作的构造函数,而第二个则是成员初值列。

(一)使用成员初值列的原因

1.效率较高

   为什么会说效率较高呢?C++规定,对象的成员的初始化动作是发生在进入构造函数的函数体之前的。也就是说赋值动作的构造函数中,成员变量theName和theLevel都先通过调用了default(默认)构造函数来设为"没有意义"的初值,再去调用copy(赋值)构造来赋值。而成员初值列的做法则避免了这一问题,不需要去调用defaule构造函数。对于大多数类型,相比之下,成员初值列的方法高效了许多。对于内置类型,其初始化和赋值的成本相同,但为了一致性,最好也通过成员初值列来初始化。
  但这里也要注意一个问题:总是在初值列中列出所有成员变量。不然还得去记住那些成员变量无需初值,若遗漏了,没有初值,还是会掉入"不明确行为"的深渊。

2.若有成员变量是const或reference(引用),只能初始化。

   如果成员变量是const或引用,那么赋值操作则是错误的,一定需要初值,那么只能通过初值化列表来初始化,而避免需要记住那些成员可以赋值,那些不可以。最简单的做法就是:总是用成员初值列,有时是必要的操作,而又往往比赋值更高效。

(二)多个构造函数的成员初值列重复问题

   许多classes拥有多个构造函数,而每个构造函数有自己的成员初值列,如果在多个构造函数的成员初值列中,许多成员变量都是一样的,就会导致不受欢迎的重复(在初值列中)和无聊的工作(对程序员而言),在这种情况下就可以将那些 “赋值表现和初始化一样好” (内置类型)的成员变量,改用赋值操作,写成一个private函数,供所有构造函数调用。

三、初始化次序的问题

   固定的"成员初始化次序":基类早于其派生类被初始化,而类的成员总是以其声明次序被初始化。

四、请记住

  • 为内置型对象进行手工初始化,因为C++不保证初始化它们。
  • 构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在class中的声明次序相同。
  • 为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static对象(因为static是内部链接,其它编译单元不可见)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值