1. 程式人生 > >條款4:確定對象被使用前已被初始化

條款4:確定對象被使用前已被初始化

區分 成員變量 運算符 public ref 析構 手動 模式 完成

一. 永遠在使用對象之前將它初始化

1.對於內置類型,手動完成初始化。 例如:int =0; 2.除了內置類型之外的類型,由構造函數進行初始化:確保每個構造函數都將對象的每一個成員進行了初始化。

二. 特別區分“賦值”和“初始化”

例如:有一個類:A中有一個成員變量string name; 有一個構造函數:A(const string &n){name=n;}//這是賦值操作而非初始化,這裏調用了默認構造函數和賦值運算符 A(const string &n):name(n){}//這是初始化而非賦值,這裏只調用了拷貝構造函數

三. 記住總是使用成員初值列

特別的:如果成員變量是const和reference(引用),就必須需要初值,而不能賦值 Tips:const和reference必須初始化。

四. 初始化順序

成員初始化順序:base classes總是先於derived classes被初始化,class的成員變量總是以 其聲明順序被初始化。即便是成員初值列中的順序不同也是如此。並且,成員初值列中的順序最好也要按照聲明順序。

五. C++對“定義於不同的編譯單元內的non-local static對象”的初始化相對次序無明確定義

編譯單元:指產出單一目標文件的源碼。基本上它是單一源碼文件加上其所含入的頭文件。 static對象:其壽命從被構造出來直到程序結束為止 local static對象:函數內的static對象,其余static對象為non-local static對象。在main()函數 結束時析構函數自動被調用。 例如A,B為兩個文件:
class A{ public: int A()const;//某個成員函數 }; extern A a; class B{ public: B(params); }; B::B(params){ int item=a.A(); } B b(params);//創建一個類型為B的變量,調用構造函數
class B中的構造函數必須要在A初始化後調用才會有確切的值,否則會出現錯誤。由於兩個是不同的文件,無法確定究竟是誰先被初始化。 解決方法:利用Singleton模式的一個常見的實現手法(單例) 將每個non-local static對象搬到自己專屬的函數內(在該函數內部聲明該對象為static),這些函數返回一個reference指向它所含的對象。 原因:C++保證,函數內的local static對象會在“該函數被調用期間”“首次遇上該對象的定義式”時被初始化。 修改後代碼如下:
class A{}; A& a()//用來替換之前的a對象 { static A m; return m; } class B{}; B::B(params){ int item=a().A(); } B& b(){ static B n; return n; }
也就是為免除“跨編譯單元的初始化次序”問題,用local static對象替換non-local static對象。

條款4:確定對象被使用前已被初始化