2010-04-14 65 views
7

在C++中,當構造函數成功完成時,對象的生命週期開始。在構造函數中,該對象尚不存在。構造函數中的例外

問:從構造函數中發出異常是什麼意思?答:這意味着施工失敗了,對象從來不存在,它的一生從未開始。 [source]

我的問題是:對於Java是否也適用?例如,如果我將this交給另一個對象,然後我的構造函數失敗,會發生什麼情況?

Foo() 
{ 
    Bar.remember(this); 
    throw new IllegalStateException(); 
} 

這是明確的嗎? Bar現在是否有對非對象的引用?

回答

8

該對象存在,但尚未正確初始化。

只要this在施工期間泄漏(不只是當您拋出異常)時,就會發生這種情況。

這是一個非常有問題的情況,因爲一些通常假定的擔保在這種情況下不成立(例如final字段在施工期間看起來可能會改變它們的值)。

因此,您應該避免在構造函數中泄漏this

This IBM developerWorks article描述了在構建對象時採取的預防措施以及這些預防措施背後的推理。雖然本文根據多線程討論了該主題,但在構建期間未知/不可信代碼獲取對this的引用時,單線程環境中可能會出現類似問題。

+1

+1 - 但在這種情況下「泄漏」被稱爲(不安全)「發佈」;例如在布洛赫。此外,這是一個好主意,更深入地解釋這一點。 – 2010-04-14 10:37:19

1

你不應該在構造函數中像打開文件一樣打開資源。改爲創建一個init方法,然後從那裏執行。那麼你很安全。

+2

*「那麼你很安全」*。那聲明顯然是假的!在構造函數中可能會導致異常的其他事物有**許多**;例如非法參數,NPE,數組索引等,甚至堆棧溢出或內存不足錯誤。 – 2010-04-14 10:44:06

+0

這是很好的建議,但也有其他情況下你可能想要一個構造函數失敗。例如,我想要一個並行迭代器,如http://stackoverflow.com/questions/3137944/best-way-to-iterate-over-two-lists-simultaneously,所以我想檢查列表是相同的大小在施工時間。 – 2013-02-08 04:08:49

0

此代碼不是異常安全的,在C++中也不是異常安全的。無論您使用哪種語言,都是同樣的錯誤。