Item 4: Make sure that objects are initialized before they’re used.
手工初始化内置对象
为内置对象进行手工初始化,因为C++
不保证初始化他们。
1 2 3 4 5
| int x = 0; const char *text = "A C-style string";
double d; std::cin >> d;
|
构造函数最好使用成员初值列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class PhoneNumber { ... }
class ABEntry { 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 numTimesConsulted; }
ABEntry::ABEntry(const std::string &name, const std::string &address, const std::list<PhoneNumber> &phones) { theName = name; theAddress = address; thePhones = phones; numTimesConsulted = 0; }
|
构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和他们在class
中的声明次序相同。
1
| ABEntry::ABEntry(const std::string &name, const std::string &address, const std::list<PhoneNumber> &phones) : theName(name), theAddress(address), thePhones(phones), numTimesConsulted(0) {}
|
local static
对象替换 non-local static
对象。
为免除”跨单元之初始化次序“问题,请以 local static
对象替换 non-local static
对象。
1 2 3 4 5 6 7
| class FileSystem { public: ... std::size_t numDisks() const; ... } extern FileSystem tfs;
|
1 2 3 4 5 6 7 8 9 10 11 12
| class Directory { public: Directory( params ); ... }
Directory::Directory( params) { ... std::size_t disks = tfs.numDisks(); ... }
|
客户使用使用:
1
| Directory tempDir( params );
|
现在初始化次序的重要性体现出来了,除非 tfs
在 tempDir
之前先被初始化,否则tempDir
的构造函数会用到尚未初始化的tfs
。但tfs
和tempDir
是不同的人在不同的时间于不同的源文件建立起来的,它们是定义于不同编译单元内的 non-local static
对象。它们初始化相对次序并无明确定义。但我们可以将 local static
对象替换non-local static
对象来解决。这也是Singleton模式的常见实现手法。
这个手法的基础在于:C++保证,函数内的 local static
对象会在调用该函数时首次遇上该对象的定义式时被初始化。
1 2 3 4 5 6 7
| class FileSystem { ... }
FileSystem& tfs() { static FileSystem fs; return fs; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Directory { ... }
Directory::Directory( params) { ... std::size_t disks = tfs().numDisks(); ... }
Directory& tempDir() { static Directory td; return td; }
|