effective c++ item04:確定對象被使用之前以先被初始化

Item04 確定對象被使用之前已被初始化

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> thePhone;
  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;
}

C++規定,對象的成員變量的初始化動作發生在進入構造函數主體之前。

在ABEntry構造函數內,theName,theAddress和thePhone都不是被初始化而是被賦值。他首先調用default構造函數爲theName,theAddress和thePhone設初值,然後立刻再對他們賦予新值。default構造函數的一切作爲浪費了。

ABEntry::ABEntry(const std::string& name,const std::string& address, const std::list<PhoneNumber>& phones)
  :theName(name),theAddress(address),thePhones(phones),numTimesConsulted(0)
{}

成員初值列(member initialization list)的做法避免了這一問題,因爲初值列中針對各個成員變量而設的實參,被拿去作爲各成員變量之構造函數的實參。本例只調用一次copy構造函數是比較高效的。


C++有着十分固定的“成員初始化次序”。初始化array時需要指定大小,因此代表大小的那個成員變量必須現有初值。

 

不同編譯單元內定義之non-local static對象的初始化次序

C++對此並無明確定義。

 

static對象,其壽命從被構造出來知道程序結束,因此staack和heap-based對象被排除。這種對象包括global對象、定義於namespace作用域內的對象、在class內、在函數內(local static)、以及在file作用域內被聲明爲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 tempDir(params);					//爲臨時文件而做出的目錄


tfs必須在tempDir之前先被初始化,但tfs和tempDir是不同的人在不同的時間於不同的源文件建立起來的,他們是定義於不同編譯單元內的non-local static對象,其次序無法確定。

解決辦法:將每個non-local static對象搬到自己的專屬函數內(該對象在次函數內被聲明爲static).這些函數返回一個reference指向它所含的對象。non-local static對象被local static對象替換了。

此技術施於tfs和tempDir身上:


class FileSystem{...};				//同前
FileSystem& tfs(){
  static FileSystem fs;
  return fs;
}

class Directory{...};				//同前
Directory::Directory(params){
  ...
  std::size_t disks=tfs().numDisks();
  ...
}
Directory& tempDir(){
  Static Directory td;
  return td;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章