【04】確定物件被使用之前已先被初始化

Andy Niu發表於2014-01-14

1、首先區分初始化和賦值。

  初始化:建立物件時賦給初始值。賦值:擦除物件當前值,並用新值代替。因此,區分初始化和賦值的關鍵是,看看物件當前是否已經有值了。

2、建立物件的時候,如果沒有初始化,物件的值是什麼?

  取決於物件的型別和物件定義的位置。

  a、如果物件是內建型別,定義在方法外,它的值為0,定義在方法內,沒有初始化。

  b、如果物件是類型別,無論定義在哪裡,都會呼叫預設構造方法,也就是說,對於類型別的物件,不存在沒有初始化的情況。

3、現在考慮,類中的資料成員,也就是欄位。類的構造方法執行兩個過程:成員初始化列表和方法內賦值。對於類型別,前者用於初始化,即copy構造;後者用於賦值,即copy賦值。對於內建型別,前者和後者都可用於初始化,如果前者沒有初始化,可在後者中初始化。

4、如果沒有在成員初始化列表中顯式初始化,出現什麼情況?

  a、如果是類型別,隱式初始化,呼叫預設構造方法;

  b、如果是內建型別,不被初始化,它的取值,按照變數初始化規則進行。它的取值依賴於所屬物件的作用域,所屬物件是區域性物件,不被初始化,所屬物件是全域性物件,初始化為0。如果內建型別是static欄位呢?static欄位必須在標頭檔案之外定義(static+const+int是個特殊情況,可以只宣告,不定義),定義時沒有初始化,取值多少?因為它是類作用域內的全域性變數,取值為0。

5、因此,對於類型別,,在方法內賦值,相當於執行了一次初始化,一次賦值。為了效率,應該在成員初始化列表中初始化。對於內建型別,兩種方式等效,為了一致性,也在成員初始化列表中進行。但是,有三種情況必須在初始化列表中進行:a、類型別沒有預設構造方法;b、引用;c、const物件。

6、類中欄位的初始化順序與初始化列表的順序無關,而是與類定義中的宣告順序保持一致。

7、static物件可認為包括:全域性物件,定義在namespace內的物件,在class內、方法內、以及file內的static物件。根據作用域可分為local static物件和non-local static物件,方法內的static物件時local static物件,其他的static物件是non-local static物件。

8、現在考慮,不同編譯單元中non-local static物件的初始化順序。C++中,對於不同編譯單元的non-local static物件的初始化順序沒有明確定義,也就是說初始化順序是不確定的。思考,為什麼C++不定義,因為做不到。因為C++是單獨分別編譯,當前編譯單元的編譯不依賴其他編譯單元的編譯。

9、那怎麼解決上面的問題呢?

  使用一個方法,方法內部建立一個local static物件,返回這個local static 物件。對於多執行緒系統,為了保證只有一個local static物件,需要使用加鎖機制。

相關文章