2013-02-19 124 views
6

我正在重寫一些代碼以消除全局變量,並且讓一個構造函數/析構函數處理某些第三方庫資源的清理,但是我擔心一些代碼會從類初始化程序列表中的其他成員初始化一個成員。我可以使用初始化器列表中初始化的C++類成員,稍後在列表中嗎?

class MyPodofoDocument { 
public: 
    // generates pdf to stream 
    MyPodofoDocument(std::stringstream *pStringStream) 
     : device(pStringStream), document(&device) 
    { 
    } 
private: 
    PoDoFo::PdfOutputDevice device; 
    PoDoFo::PdfStreamedDocument document; 
    PoDoFo::PdfPainter painter; 
}; 

使用這個類並不需要看到所有進入使用庫的詳細信息的代碼,但我隱瞞他們的方式使得它依賴於使用成員初始化其他成員,它擊中前構造函數的實際代碼塊,它有一個有效的指針。

它在單元測試框架中工作,所以我的問題基本上是「這是好的,便攜的和安全的嗎?」

回答

8

的成員在順序進行初始化聲明它們,從上到下

PoDoFo::PdfOutputDevice device; 
PoDoFo::PdfStreamedDocument document; 
PoDoFo::PdfPainter painter; 

因此它是安全的使用device初始化document

+0

此外,獲取地址或將引用綁定到尚未構建的成員是合法的(即,如果接收者不使用*對象,但只存儲引用/指針)。 – 2013-02-19 20:48:25

+0

傳遞是合法的,但在語義上是錯誤的,因爲你將一個指針傳遞給尚未構造的東西。 – 2013-02-19 20:53:13

+0

@AlexChamberlain:它一定沒有錯,但可能需要重新檢查。 – GManNickG 2013-02-19 21:12:04

4

的種類。規則是成員變量按照它們在類聲明中聲明的順序進行初始化。

對您而言,自devicedocument之前宣佈無誤。

但是,在下面的情況下,儘管初始化程序列表的順序仍然存在未定義的行爲。

class A { 
public: 
    A(int i) : b(i), a(b) { } 
private: 
    int a; 
    int b; 
} 
+1

即使它是安全的*只要變量之間的依賴關係與聲明順序*相同,恕我直言,這不是很好的做法。這樣的代碼應該儘可能避免,因爲在重構你的課程時錯誤地修改聲明順序太容易了,從而觸發UB,正如Alex的例子所顯示的那樣。換句話說,這是正確的,但非常脆弱。 – syam 2013-02-19 20:24:06

+1

@syam:我不太確定......我曾經這麼想過,但如果初始化程序失靈,編譯器會很容易地警告您(編譯器會將您的注意力引向潛在的UB)在某些情況下,它可能有助於引用同一類型的不同成員。 – 2013-02-19 20:49:51

+0

它不僅適用於相同類型的課程,任何存在變量之間真正依賴關係的東西,但也需要存儲變量的地方。 – 2013-02-19 20:51:20

相關問題