2011-09-27 32 views
9

假設我有:C++:我應該初始化在構造函數體中分配給NULL的指針成員嗎?

// MyClass.h 
class MyClass 
{ 
    public: 
    MyClass(); 

    private: 
    Something *something_; 
} 

// MyClass.cpp 
MyClass::MyClass() 
{ 
    something_ = new Something(); 
} 

我應該在MyClass的構造函數的構造函數初始化列表初始化something_爲NULL(或0)?或者是不必要的,因爲我在構造函數的主體中賦值給它?建議的做法是什麼?

+8

爲什麼不只是初始化指針擺在首位? MyClass :: MyClass():something_(new Something())' –

+0

哦,這是最佳做法嗎? – User

+3

總是在構造函數體中優先考慮賦值。並且使用像'shared_ptr'或'scoped_ptr'這樣的智能指針來代替原生指針,這樣即使在例外的情況下,清理也是自動的。 –

回答

11

通常你只能分配一次,在初始化列表或身體,除非身體初始化可能會或可能不會發生,或有前提條件的代碼:

MyClass::MyClass() 
{ 
    //this code must happen first 
    // _now_ max is known 
    something_ = new Something(max); 
} 

MyClass::MyClass() 
{ 
    if (max) 
     something_ = new Something(max); 
    else 
     something_ = NULL; 
} 

MyClass::MyClass() 
    : something_(new Something()) 
//as pointed out in the comments, use smart pointers 
{ 
} 
+5

用初始化列表中的動態分配結果初始化指針數據成員是個壞主意。太多的事情可能會出錯。例如,如果在構建其他數據成員期間拋出異常,您如何知道哪些數據成員已初始化,以便銷燬動態分配的對象?即使你使用了功能試塊,你也不知道哪裏建設失敗。 (當然,應該使用智能指針,在這種情況下,初始化列表中的動態分配可以,但使用普通指針時要小心)。 –

+1

@詹姆斯:當然,應該使用智能指針而不是原生指針。 (哈,你剛剛編輯了你的評論說)。 –

+0

如果我創建不同的對象,第一個需要第二個作爲參數?你可以在這種情況下使用初始化器,還是與你最大的例子一樣? (例如':something_(新東西()),somethingElse_(新SomethingElse(東西_))...') – User

2

一般來說 - 沒有。但是如果你的構造函數指針中的某個地方在被初始化之前被使用了,那麼你會得到未定義的行爲。然而,你遇到的最大問題是這個 - 如果在構造函數中拋出異常,它的析構函數不會被調用。所以想象你有兩個指向對象的指針,第一個對象的分配成功,而第二個分配失敗,在這種情況下,最終會導致資源泄漏。這可以通過使用「智能」指針來解決。但在這種情況下,它們將在初始化列表中初始化,如果您不想爲它們分配兩次值,那麼您最好在那裏分配內存,而不是在構造函數體中分配內存。

+0

我沒有想到潛在的異常安全問題。 –

1

沒有必要的,特別是如果你立即初始化但是,如果初始化不是那麼明顯,那麼爲什麼不是NULL,以避免意外訪問未初始化的變量。

  • 性能開銷最小
  • 節省了瘋狂的缺陷尋找這麼多的調試/故障排除時間
+0

*'瘋狂的bug狩獵'* - 絕對。我現在正在尋找一個資源泄漏(一個Windows用戶對象),並且在初始化程序列表中最常遇到的問題是'new'調用:在初始化程序列表的「原子」世界中沒有前/後。 – Wolf

相關問題