跳至主要內容

LincZero大约 2 分钟

为什么要初始化

如果你这么写:

int x;

在某些语境下x保证被初始化(为0),但在其他语境中却不保证

而最佳处理办法就是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工完成此事。例如:

int x = 0; 								// 对int进行手工初始化
const char* text = "A C-style string"; 	// 对指针进行手工初始化
										// 〔亦见条款3)
double d;
std::cin >> d; 							// 以读取input stream的方式完成初始化.

别混淆了赋值(assignment)和初始化(initialization)

这个规则很容易奉行,重要的是别混淆了赋值(assignment)和初始化(initialization)。

class PhoneNumber { ... };
class ABEntry { 			// ABEntry = “Address Book Entry”
public:
	ABEntry (const std::string& name, const std::string& address,
			 const std::list<PhoneNumber>& phones);
private:
	std::string theName;
	std::string theAddress;
	std: :1ist<PhoneNumber> thePhones;
	int numTimesConsulted;
};
ABEntry::ABEntry (const std::string& name, const std::string# address,
				  const std::list<PhoneNumber>& phones)
{
    theName = name; 		// 这 些 都 是 赋 值 (assignments) ,
    theAddress = address; 	// 而 非 初 始 化 (initializations) 。
    thePhones = phones;
    numTimesConsulted = 0;
}

C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前前。在ABEntry构造函数内,theName,theaddress和thephones都不是被初始化,而是被赋值。初始化的发生时间更早。

ABEntry构造函数的一个较佳与法是,使用所谓的member initialization list (成员初值列) 替换赋值动作

RBEntry::RBEntfYy (const std::stringg name, const std::string& address,
				   const std::1ist<PhoneNumber>8 phones)
	:theName (name) ,
    theAddress (address), 	// 现 在 , 这 些 都 是 初 始 化 (initializations)
    thePhones (phones),
    numTimesConsulted (0)
{ } // 现 在 , 构 造 函 数 本 体 不 必 有 任 何动 作

所以说,列表初始化 是真正的初始化,会在构造函数前发生。而构造函数内赋值,则只是赋值而已。

假设RBEntry有一个光参数构造出数,我们可将它实现如下:

ABEntry::ABEntry()
	:theName () , // 调 用 theName 的 default 构 造 函 数 :
	theAddress () , // 为 theaddress 做 类 做 动 作 :
	thePhones () , // 为 thePhones 做 类 似 动 作 ;
	numTimesConsulted (0) // 记 得 将 numTimesConsul ted 显 式 初 始 化 为 0
{};

C++有着十分固定的“成员初始化次序“。是的,次序总是相同:baseclasses更早于其derivedclasses被初始化(见条款12),而class的成员变量总是以其声明次序被初始化。