读取未初始化的值会导致不明确的行为。
最佳处理办法是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工初始化。
- int x = 0;
- const char * text = "A C-style string";
- double d;
- std::cin>>d;//以读取input stream的方式完成初始化
内置类型以为的任何类型,初始化责任落在构造函数身上。
规则很简单:确保每一个构造函数都将对象的每一个成员初始化。
“重要的是别混淆了赋值和初始化”??
- using namespace std;
- 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>& phones)
- {
- theName = name;//这些都是赋值而非初始化
- theAddress = address;
- thePhones = phones;
- numTimesConsulted = 0;
- }
- ABEntry::ABEntry(const string& name, const string& address,
- const list<PhoneNumber>& phones)
- :theName(name),theAddress(address),thePhones(phones),numTimesConsulted(0)
- {}//这些都是初始化
初始化的效率要高
有些情况下即使面对的成员变量属于内置类型也一定得使用初始值。如果成员变量是const或引用,它们就一定需要初值,不能被赋值,为了避免需要记住成员变量何时必须在成员初值列中初始化,何时不需要,最简单的做法就是:总是使用成员初值列
基类更早于继承类被初始化。
当你在成员初值列中条列各个成员时,最好总是以其声明次序为次序。
“不同编译单元内定义之non-loacl static对象的初始化次序”??
1.所谓static对象,其寿命从被构造出来直到程序结束为止,因此stack和heap-based对象都被排除,这种对象包括global对象,定义于namespace作用域内的对象,在classes内,在函数内,以及在file作用域内被声明为static的对象。
函数内的static对象被称为local static对象(因为他们对函数而言是local),其他static对象称为non-local static对象,程序结束时static对象会被自动销毁,也就是他们的析构函数会在main()结束时被自动调用。
2.所谓编译单元是指产出单一目标文件的那些源码,基本上它是单一源码文件加上其所含入的头文件。
//C++对“定义于不同编译单元内的non-loacl static对象”的初始化次序并无明确//定义。
- class FileSystem
- {
- public:
- ...
- std::size_t numDisks() const;
- ...
- };
- extern FileSystem tfs;//预备给客户使用的对象
- class Directory
- {
- public:
- Directory(params);
- ...
- };
- Directory::Directory(params)
- {
- ...
- std::size_t disks = tfs.numDisks();//使用tfs对象
- }
- //---------------------
- //假设客户决定创建一个Directory对象,用来存放临时文件
- Directory tempDir(param);//为临时文件创建目录
- /**
- 除非tfs在tempDir之前被初始化,否则tempDir的构造函数会用到尚未初始化的tfs,
- 但是不确定tfs会在tempDir之前被初始化。
- */
修改--->
将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static)。这些函数返回一个引用指向它所含的对象。然后用户调用这些函数,而不是直接指涉这些对象。non-local static对象被loacl static对象替换了,这是Singleton模式的一个常见实现手法。
这个手法的基础在于:C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化。所以如果你以“函数调用”(返回一个引用指向local static对象)替换“直接访问non-local static对象”,保证了你所获得的那个引用将指向一个历经初始化的对象。
- class FileSystem{...};//同前
- FileSystem& tfs() //这个函数用来替换tfs对象;它在FileSystem class
- { //中可能是个static
- static FileSystem fs;//定义并初始化一个local static对象
- return fs; //返回一个引用指向上述对象
- }
- class Directory{...};
- Directory::Directory(params)
- {
- std::size_t disks = tfs().numDisks();
- }
- Directory& tempDir() //这个函数用来替换tempDi日对象;
- { //它在Direcctory class中可能是个static
- static Directory td; //定义并初始化loacl static对象
- return td; //返回一个引用指向上述对象
- }
1.为内置对象进行手工初始化,因为C++不保证初始化它们。
2.构造函数最好使用成员初值列,而不是在构造函数本体内使用赋值操作,初值列列出的成员变量,其排列次序应该和它们在class中声明次序相同。
3.为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static 对象。