《Effective C++讀書筆記》--條款04:確定對象被使用前已先被初始化

對於C++來說,定義一個值未初始化,其值是一個不確定的數,而當我們使用未初始化的值會導致UB,在不同的平臺上表現不一樣,總之會給程序帶來不可預知的行爲,我們要盡力避免。所以對於內置類型來說,我們要儘量在使用對象之前將他初始化,至於內置成員之外的類型,初始化的任務落在構造函數上,我們要確保每個構造函數將每個對象的每一個成員都初始化。此時有兩種方法,一是在初始化列表中初始化,二是在構造函數中賦值。對此,我們要理清初始化和賦值的區別:
--初始化:

初始化是在進入構造函數之前就完成的動作,在構造好對象時就將數據填充進去,調用一次默認構造函數。

--賦值:

對於賦值操作來說則是先調用默認構造函數,然後再調用拷貝賦值運算符。效率比初始化列表要低,因爲他多調用了一次賦值操作。

以上是對於非內置類型來說的,對於內置類型,兩種操作效率差別不大。

接下來討論初始化列表,有一點需要特別注意,就是初始化的順序由聲明成員的順序所決定,即使在初始化列表中以不同的次序出現,因此我們要注意根據聲明的先後順序決定在初始化列表中的順序。有三種情況下必須使用初始化列表:

1、數據成員是一個引用,由於引用必須給予初值,因此引用必須使用初始化列表。

2、const類型不可賦值,必須使用初始化列表給予初始值。

3、繼承類中調用基類的初始化構造函數,即先構造基類對象,必須使用初始化列表。

最後一點,也是最容易被忽視的一點就是,不同編譯單元內定義的non-local static對象的初始化次序。我們知道對於函數內的靜態成員來說,該對象會在第一次調用該函數,首次遇上該對象之定義式時被初始化。舉一個例子,當我們在客戶端構造一個Directory類時,在其構造函數中使用到了tfs這個對象,但此時有可能這個對象還未初始化,此時就會出現問題,但我們以函數調用來取代直接調用該成員就可以避免該成員未被初始化的問題,因爲我們在函數體內就定義並初始化了該對象,並且返回了該對象的一個引用,如此就保證了我們在使用時已經初始化了該對象。

總結以上內容爲三點:
--1、手動初始化內置對象

--2、使用初始化列表初始化對象的所有成分。

--3、設計函數調用等方法避免調用未初始化的對象。



發佈了73 篇原創文章 · 獲贊 15 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章