2011-08-16 50 views
8

我一直認爲創建一個新對象總是會調用對象的默認構造函數,而構造函數是顯式的還是由編譯器自動生成都沒有區別。據this highly regarded answer到一個不同的問題,這改變了C++ 98和C++ 03之間一種微妙的方式和現在的作品,像這樣:C++ 03中default-initialize和value-initialize的區別?

struct B { ~B(); int m; }; // non-POD, compiler generated default ctor 
new B; // default-initializes (leaves B::m uninitialized) 
new B(); // value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined. 

誰能告訴我:

  1. 爲什麼標準發生了變化,例如,這給了什麼好處呢?
  2. 什麼exacly做的術語「默認初始化」和「值初始化」代表什麼?
  3. 該標準的相關部分是什麼?
+0

新C++ 11標準的相關部分是8.5(「初始化器」)子句5,6,7。 –

+0

也許它給了人們使用默認ctor的選項。在舊版本的C++中,當沒有參數時通常會錯過括號。因此,對新選項加上括號會影響較少的遺留代碼。 – QuentinUK

+0

我不會稱之爲改變,而是改正。它至少在例如上下文中是有意義的。 std :: map其中由[]創建的值是初始值,因此例如std :: map 所有的U *都被初始化爲0 – PlasmaHH

回答

2

我不知道周圍的變化(或怎樣的標準是之前)的基本原理,但它是如何,基本上默認初始化要麼調用用戶定義的構造或什麼都不做(大量的手揮動:這是遞歸應用於每個子對象,這意味着具有默認構造函數的子對象將被初始化,沒有用戶定義的構造函數的子對象將被初始化)。

這屬於只支付你想要的語言的哲學,並與C兼容的所有類型是C兼容的。另一方面,您可以請求的值初始化,這相當於爲對象調用默認構造函數,它將初始化爲0轉換爲其他子對象的適當類型。

這在第8.5節描述的初始值設定,並且這是不平凡導航通過。爲定義零初始化缺省初始化值初始化是第五段落:

要零初始化類型T的對象是指:

- 如果T是一個標量類型(3.9),該對象被設置爲值0(零)轉換爲T;

- 如果T是一個非工會類型,每個非靜態數據成員,並且每個基類子對象zeroinitialized;

- 如果T是一個聯合類型,對象的第一個命名數據member89)的零初始化;

- 如果T是一個數組類型,每一個元素是零初始化;

- 如果T是引用類型,則不執行初始化。

爲默認初始化類型T的對象是指:

- 如果T是一個非POD類型(第9節),T的默認構造函數被調用(以及初始化是形成不良的,如果T沒有可訪問的默認構造函數);

- 如果T是數組類型,則每個元素都是默認初始化的;

- 否則,該對象是零初始化的。

要值初始化類型T的對象是指:

- 如果T是一個類型(第9節)與用戶聲明的構造(12.1),然後對T中的默認構造函數被調用(和如果T沒有可訪問的默認構造函數,則初始化不合格);如果T是一個沒有用戶聲明構造函數的非聯合類類型,那麼T中的每個非靜態數據成員和基類組件都被初始化;

- 如果T是一個數組類型,則每個元素都進行了值初始化;

- 否則,該目的是零初始化

,對於缺省初始化或引用類型的實體的值初始化調用格式不正確的程序。如果T是cv限定類型,則c的非限定版本T用於零初始化,缺省初始化和值初始化的這些定義。

+0

你的引導段落已經將Default-初始化的行爲定義爲無論是使用ctor還是其左側未初始化。我的問題是8.5初始化程序部分的包含引用的解釋,該部分定義了作爲最後一步的默認初始化...「 - 否則對象將被初始化爲零」。它似乎表明,如果沒有ctor,那麼使用zero-initialize的規則,而不是初始化。 – TheChrisONeil

+0

@CBO:特別引用來自C++ 03,在C++ 11中最後一項已更改並讀取:*否則,不執行初始化*。此時的關鍵是幾段後面寫的內容。對於沒有提供初始化程序的對象,在C++ 03中,該對象保持未初始化狀態(in/9),在C++ 11中,該對象是* default-initialized *(/ 12)。不知道這是否回答您的問題 –

+0

有道理,並感謝您跟進。我會建議更新你的帖子,現在包括C++ 11的內容。 – TheChrisONeil