读取未初始化的值会导致不明确的行为。

 

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

 

  1. int x = 0; 
  2. const char * text = "A C-style string"
  3. double d; 
  4. std::cin>>d;//以读取input stream的方式完成初始化 

内置类型以为的任何类型,初始化责任落在构造函数身上。

规则很简单:确保每一个构造函数都将对象的每一个成员初始化。

“重要的是别混淆了赋值和初始化”??

 

  1. using namespace std; 
  2.  
  3. class PhoneNumber{...}; 
  4. class ABEntry 
  5. public
  6.   ABEntry(const string& name, const string& address,  
  7.           const list<PhoneNumber>& phones); 
  8. private
  9.   string theName; 
  10.   string theAddress; 
  11.   list<PhoneNumber> thePhones; 
  12.   int numTimesConsulted; 
  13. }; 
  14. ABEntry::ABEntry(const string& name, const string& address,  
  15.                  const list<PhoneNumber>& phones) 
  16.   theName = name;//这些都是赋值而非初始化 
  17.   theAddress = address; 
  18.   thePhones = phones; 
  19.   numTimesConsulted = 0; 
  20.  
  21. ABEntry::ABEntry(const string& name, const string& address, 
  22. const list<PhoneNumber>& phones) 
  23. :theName(name),theAddress(address),thePhones(phones),numTimesConsulted(0) 
  24. {}//这些都是初始化 

初始化的效率要高

有些情况下即使面对的成员变量属于内置类型也一定得使用初始值。如果成员变量是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对象”的初始化次序并无明确//定义。

 

  1. class FileSystem 
  2. public
  3.   ... 
  4.   std::size_t numDisks() const
  5.   ... 
  6. }; 
  7. extern FileSystem tfs;//预备给客户使用的对象 
  8.  
  9. class Directory 
  10. public
  11.   Directory(params); 
  12.   ... 
  13. }; 
  14. Directory::Directory(params) 
  15.   ... 
  16.   std::size_t disks = tfs.numDisks();//使用tfs对象 
  17. //---------------------
  18. //假设客户决定创建一个Directory对象,用来存放临时文件 
  19. Directory tempDir(param);//为临时文件创建目录 
  20.  
  21. /** 
  22. 除非tfs在tempDir之前被初始化,否则tempDir的构造函数会用到尚未初始化的tfs,
  23. 但是不确定tfs会在tempDir之前被初始化。 
  24. */ 

修改--->

将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static)。这些函数返回一个引用指向它所含的对象。然后用户调用这些函数,而不是直接指涉这些对象。non-local static对象被loacl static对象替换了,这是Singleton模式的一个常见实现手法。

这个手法的基础在于:C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化。所以如果你以“函数调用”(返回一个引用指向local static对象)替换“直接访问non-local static对象”,保证了你所获得的那个引用将指向一个历经初始化的对象。

 

  1. class FileSystem{...};//同前 
  2. FileSystem& tfs()  //这个函数用来替换tfs对象;它在FileSystem class 
  3. {                 //中可能是个static 
  4.   static FileSystem fs;//定义并初始化一个local static对象 
  5.   return fs;  //返回一个引用指向上述对象
  6. class Directory{...}; 
  7. Directory::Directory(params) 
  8.   std::size_t disks  = tfs().numDisks(); 
  9.  
  10. Directory& tempDir() //这个函数用来替换tempDi日对象;
  11. {  //它在Direcctory class中可能是个static
  12.   static Directory td; //定义并初始化loacl static对象
  13.   return td;  //返回一个引用指向上述对象

 

1.为内置对象进行手工初始化,因为C++不保证初始化它们。

2.构造函数最好使用成员初值列,而不是在构造函数本体内使用赋值操作,初值列列出的成员变量,其排列次序应该和它们在class中声明次序相同。

3.为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static 对象。