C++ 看上去在对象的值的初始化方面变化莫测。例如,如果你这样做,
int x;
在某些情形下,x 会被初始化(为 0),但是在其它情形下,也可能没有。如果你这样做,
class Point {
int x, y;
};
...
Point p;
p 的 data members(数据成员)有时会被初始化(为 0),但有时没有。如果你从一个不存在 uninitialized objects(未初始化对象)的语言来到 C++,请注意这个问题,因为它非常重要。
读取一个 uninitialized values(未初始化值)会引起 undefined behavior(未定义行为)。在一些平台上,读一个 uninitialized value(未初始化值)会引起程序中止,更可能的情况是得到一个你所读的那个位置上的 semi-random bits(半随机二进制位),最终导致不可预测的程序行为和恼人的调试。
现在,有一些描述关于什么时候能保证 object initialization(对象初始化)会发生什么时候不能保证的规则。不幸的是,这些规则很复杂——我觉得它复杂得无法记住。通常,如果你使用 C++ 的 C 部分(参见 Item 1),而且 initialization(初始化)可能会花费一些运行时间,它就不能保证发生。如果你使用 C++ 的 non-C 部分,事情会有些变化。这就是为什么一个 array(数组)(来自 C++ 的 C 部分)不能确保它的元素被初始化,但是一个 vector(来自 C++ 的 STL 部分)就能够确保。
处理这种事情的表面不确定状态的最好方法就是总是在使用之前初始化你的对象。对于 built-in types(内建类型)的 non-member objects(非成员对象),需要你手动做这件事。例如:
int x = 0; // manual initialization of an int
const char * text = "A C-style string"; // manual initialization of a
// pointer (see also Item 3)
double d; // "initialization" by reading from
std::cin >> d; // an input stream
除此之外的几乎全部情况,initialization(初始化)的重任就落到了 constructors(构造函数)的身上。这里的规则很简单:确保 all constructors(所有的构造函数)都初始化了 object(对象)中的每一样东西。
这个规则很容易遵守,但重要的是不要把 assignment(赋值)和 initialization(初始化)搞混。考虑下面这个表现一个通讯录条目的 class(类)的 constructor(构造函数):
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::list<PhoneNumber> thePhones;
int num TimesConsulted;
};
ABEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones)
{
theName =