2010-09-13 161 views
10

如果我沒有定義自己的構造函數,Base *b = new Base;Base *b = new Base();之間是否有區別?`Base * b = new Base;`vs`Base * b = new Base();`沒有定義我自己的構造函數

+0

是第一個合法的C++代碼嗎? – 2010-09-13 03:55:34

+0

@Rafe:是的,第一個是完全合法的。 (請參閱我的答案中的鍵盤鏈接) – 2010-09-13 03:58:34

+2

接受的答案是**錯誤**。'new T'會*默認初始化*對象,而'new T()'會*初始化*它。 – 2010-09-13 08:28:44

回答

8

初始化是一種遵循標準的PITA ...然而,兩個已經存在的答案在他們錯過的時候是不正確的,這使得他們肯定沒有區別。

在沒有用戶定義的構造函數的類中調用new Tnew T()有很大區別。在第一種情況下,對象將是默認初始化,而在第二種情況下,它將被初始化*值。如果對象包含任何POD子對象,那麼第一個將離開POD子對象初始化,而第二個將各個子元件設置爲0。

struct test { 
    int x; 
    std::string s; 
}; 
int main() { 
    std::auto_ptr<test> a(new test); 
    assert(a->s.empty()); // ok, s is string, has default constructor 
          // default constructor sets it to empty 
// assert(a->x == 0); // this cannot be asserted, the value of a->x is 
          // undefined 
    std::auto_ptr<test> b(new test()); 
    assert(b->s.empty()); // again, the string constructor sets to empty 
    assert(b->x == 0); // this is guaranteed by *value-initialization* 
} 

對於漫長的道路... 爲用戶默認初始化定義的類意味着調用默認的構造函數。在沒有用戶提供的默認構造函數的情況下,它將調用隱式定義的默認構造函數,它相當於一個具有空初始化列表和空主體的構造函數(test::test() {}),這又會導致每個非空值的默認初始化 -POD子對象,並保留所有POD子對象未初始化。由於std::string具有用戶(通過包括標準庫編寫器的用戶的某種定義)提供了構造函數,它將調用此構造函數,但它不會對x成員執行任何實際初始化。

也就是說,對於一個類用戶提供的默認構造函數,new Tnew T()是相同的。對於沒有這樣的構造函數的類,它取決於類的內容。

+0

for non native發言者(包括我):(1)http://en.wiktionary.org/wiki/PITA(2)http://stackoverflow.com/questions/146452/what-are-pod-types-in-c – 2010-09-13 08:38:14

+0

謝謝對於鏈接@afriza。 – 2010-09-13 08:51:34

+0

+1:現在指出我的迴應中的錯誤,並+1爲一個很好的答案,將它排隊以後!!做成我最喜歡的問題以及 – Chubsdad 2010-09-13 08:58:55

3

編輯:SEE @大衛的回答 - 這是錯誤的,但我不能刪除它,因爲它被接受

有在任何情況下沒有什麼區別 - 如果你把它定義不要緊,你的自己的構造函數與否。

唯一的區別是對於原始類型(即intfloat),添加()會將該值初始化爲零。 (Demonstration on Codepad

參見本實施例中(輸出是上codepad

#include <iostream> 

struct ConstructorChecker 
{ 
    ConstructorChecker() 
    { 
     std::cout << "Hey look! A new constructor checker!" << std::endl; 
    } 
}; 

struct BasicClass 
{ 
}; 

int main() 
{ 
    //Note constructor called in both cases. 
    ConstructorChecker *one = new ConstructorChecker; 
    delete one; 
    ConstructorChecker *two = new ConstructorChecker(); 
    delete two; 
    //Same deal -- just because the compiler provides the constructor doesn't mean 
    //it behaves any differently. 
    BasicClass *basic = new BasicClass; 
    delete basic; 
    BasicClass *basic2 = new BasicClass(); 
    delete basic2; 
    return 0; 
} 
+0

微妙而奇妙的差異。關於C++的那種讓你想知道的事情:_why_? – wilhelmtell 2010-09-13 03:52:43

+0

我的錢與現有C++代碼的向後兼容性。 – 2010-09-13 03:57:06

+3

@Mike:向後兼容性沒有任何意義,因爲'new'永遠是那樣的。我的猜測是,他們不希望用戶必須付費將內存初始化爲零,但他們希望提供'new'樣式的'calloc'替換(它要求將內存初始化爲零)。 '()'是一個合理的語法,因爲它看起來像你正在調用一個構造函數,它初始化任何其他類型的值。 – 2010-09-13 04:00:26

-1

如比利提到的,兩者都是同一個。

這被稱爲'價值初始化語法'($ 8.5/7)。

一個對象,其初始化是 空的圓括號,即(), 應值初始化。

+1

您引用了標準的正確部分,但您卻沒有注意到它的重要性...... – 2010-09-13 07:54:58