(一)
读取未初始化的值会导致不明确的行为;array不保证其内容被初始化,但是vector却有此保证;
最佳处理办法:永远在使用对象之前先将它初始化;确保每一个构造函数都将对象的每一个成员初始化;
(二)利用构造函数成员初值列来初始化对象而不要利用在构造函数体内赋值的方法,原因在代码后面表述:
不要用下面这种方法:
class PhoneNumber{...};
class ABEntry {
public:
ABEntry(const string& name, const string& address, const list<PhoneNumber>& phones);
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
int numTimesConsulted;
};
ABEntry::ABEntry(const string &name, const string &address, const list<PhoneNumber> &phone) {
theName = name;
theAddress = address;
thePhones = phones;
numTimesConsulted = 0;
}
要用这种方法:
class PhoneNumber{...};
class ABEntry {
public:
ABEntry(const string& name, const string& address,
const list<PhoneNumber>& phones);
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
int numTimesConsulted;
};
ABEntry::ABEntry(const string &name, const string &address,
const list<PhoneNumber> &phone)
:theName(name),
theAddress(address),
thePhones(phones),
numTimesConsulted(0)
{ }
原因:第一种方法先调用default构造函数构造成员变量,然后再调用赋值operator。而第二种方法直接拿参数调用复制构造函数进行初始化。所以第二种方法效率比第一种要高。
(三)
准则:规定总是在初值列中列出所有的成员变量,以免还得记住哪些成员变量可以无需初值。如果成员变量是const或者references就一定要初始化。
规定:总是使用成员初值列!
(四)C++中成员初始化顺序:base classes更早于其derived classes被初始化,而class的成员变量总是以其声明次序被初始化。即使成员变量在初值列的顺序跟声明的时候不同,初始化的顺序还是按照声明的顺序来的。
(五)
现在假设有两个源码文件,每一个内至少含有一个non-local static对象。如果一个源码的non-local static对象的初始化利用了另一个源码的non-local static对象,但是后者还没初始化,这时候要怎么办!下面举例子:
第一个源码:
<pre class="cpp" name="code">class FileSystem {
public:
size_t numDisks() const;
};
extern FileSystem tfs;
第二个源码:
class Directory {
public:
Directory( params );
};
Directory::Directory( params ) {
size_t disks = tfs.numDisks();
}
现在创建一个对象:
Directory tempDir( params );
这个时候就必须要求tfs在tempDir之前构造,但是他们来自两个不同的人在不同的时间于不同的源码文件建立起来的,他们是定义于不同编译单元内的non-local static对象。C++标准对于这个并没有明确的规定,所以我们要改善我们的代码:
方法:将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static),用户直接调用这些函数,而不是直接指涉这些对象!其实就是non-local static对象被local static对象给替换了!
class FileSystem {
public:
size_t numDisks() const;
};
FileSystem& tfs() {
static FileSystem fs;
return fs;
}
class Directory {
public:
Directory( params );
};
Directory::Directory( params ) {
size_t disks = tfs().numDisks();
}
Directory& tempDir() {
static Directory td;
return td;
}
Directory tempDir( params );
这样改的话,用户在建立Directory的对象的过程中,会先调用tfs(),这样就保证了两个non-local static变量的构造顺序。在这里就保证了:tfs在tempDir之前构造。
这个手法的基础:C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化。
请记住:
(1)为内置型对象进行手工初始化,因为C++不保证初始化它们。
(2)构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在class中的声明次序相同。
(3)为免除“跨编译单元之初始化次序”问题,请以local static对象替换non_local_static对象,方法:为每一个non_local_static对象创建一个reference-returning函数。