1. 默認初始化
如果定義變量時沒有指定初值,則變量會被默認初始化,此時變量被賦予了“默認值”。
對於類類型的變量來說,初始化都是依靠構造函數來完成的。因此,即使定義某個類的變量(對象)時沒有提供初始化式,我們也能通過類的默認構造函數來完成初始化。即,“默認值”由默認構造函數來決定(前提是該類有默認構造函數)。
對於內置類型的變量來說,當定義沒有初始化式的變量時,系統有時會幫我們初始化變量。“默認值”由定義的位置決定:定義於任何函數體之外的變量被初始化為0;定義在函數體內部的變量默認值是未定義的,不會由系統自動初始化,雖然值是未定義的,但是仍然是有一個默認值的。即,“默認值”由定義的位置決定。
2. 針對const類型的默認值
const對象一旦創建后,其值就不能再改變,所以const對象必初始化(注意,必須由用戶來決定怎么初始化從而給定默認值,而不是依靠系統)。
對於內置類型變量來說,我們自己初始化時,只有一種辦法,就是提供值。即const內置類型變量無法默認初始化,系統也不會提供默認值。因此類似以下的代碼語法上就是錯的:
const int ival; // 錯誤,ival沒有初始化
對於類類型變量來說,我們通過構造函數來完成變量的初始化,這當然也包括了默認構造函數(必須是用戶自定義的默認構造函數,而非系統合成的默認構造函數),因此可以在定義對象時,不提供初始化式:
const A object; // 正確,通過默認構造函數來初始化
3. 合成的默認構造函數定義為delete的一種情況
1. 編譯器創建的合成的默認構造函數按以下規則初始化類的數據成員:
-> 如果該數據成員有類內初始值,則在默認構函數中用類內初始值來初始化成員。
-> 如果該數據成員沒有類內初始值,則在默認構造函數中該成員采取默認初始化。(更確切的說,是使用該成員的默認值)
2. 聯系《primer 5th》page450-451
-> 如果在類中,有一個沒有類內初始化器的const內置類型成員,則該成員沒有辦法初始化(因為const內置類型變量必須由用戶自己來初始化,注意:const的內置類型變量是無法默認初始化的)。因為該成員沒有辦法自己初始化(通過以上1的兩種方式初始化),因此該類的默認構造函數定義為刪除(delete)。
-> 如果在類中,有一個沒有類內初始化器的const類類型成員,且其類型沒有顯示定義默認構造函數(導致該const類類型成員也沒有辦法默認初始化),因此該類的默認構造函數定義為刪除(delete)。
-> 如果在類中,有一個沒有類內初始化器的類類型成員,且其類型沒有定義默認構造函數(導致類類型成員也沒有辦法默認初始化),因此該類的默認構造函數被定義為刪除(delete)。
有關此處的delete情況小結:
1. 首先需要明確內置類型變量是否可以默認初始化取決於變量位置,但無論如何,對於非const內置類型變量而言,一定會有一個默認值,即便其也許是未定義的;而對於類類型變量,如果要有默認值,必須要有默認構造函數,如果沒有默認構造函數,其無法進行默認初始化。
2. 對於沒有類內初始化器的內置類型成員來說,const使成員失去了擁有默認值的能力。
3. 對於沒有類內初始化器的類類型成員來說,加const,必須有用戶自定義的默認構造函數,才可以默認初始化,從而擁有默認值。不加const,那么只要有默認構造函數(隱式、顯示均可)即可默認初始化,從而擁有默認值。
4. 本質含義
如果一個類有數據成員不能默認構造(更確切的說是無法擁有默認值)、拷貝、復制或銷毀,則對應的成員函數將被定義為delete。
5. 與c++03標准區別
系統合成的構造函數定義為delete是c++11標准中提出的概念。
對於c++03標准而言,在有默認構造函數,且不是用戶自定義的默認構造函數的情況下,那么我們默認隱式的默認構造函數一定是存在的。
