程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 關於構造函數和異常的分析

關於構造函數和異常的分析

編輯:C++入門知識

如果構造函數內發生異常,已經分配的資源是不會自動釋放的,比如

~ std::runtime_error(~~= = ~** main( argc,  ** 

運行結果如下:

into A constructor

into D constructor

into B constructor

into C constructor

terminate called after throwing an instance of 'std::runtime_error'

what(): exception from C constructor

對象c在構造過程中拋出異常,指針b指向的內存空間不會被釋放。

如何釋放b的內存呢?首先我們可以看出c++是不會調用析構函數的,因為析構函數不知道對象已經構造了多少,哪些資源該釋放,哪些不該釋放,當然編譯器可以記錄這些內容,但是會嚴重影響效率。另外在語義上,c++認為,對象的生命周期是構造函數正常結束至析構函數結束之間,構造不完全的對象是一個沒有生命的東西,是不存在的,你不能對一個不存在的對象調用析構函數。編譯器默認會做的只是釋放對象d的內存空間。對象b指向的堆內存可以通過使用異常顯示釋放

= = (std::runtime_error &==}

運行結果如下:

into A constructor

into D constructor

into B constructor

into C constructor

into D constructor catch

into B destructor

into D destructor

into A destructor

b被正常釋放了,我們再做一下改變,將b和c的構造放到初始化列表中做,將D的構造函數改成下面這樣,

D::D() : A(),b( B()),c(

我們繼續使用異常,會不會有效?

D() :A(), b( B()), c((std::runtime_error &

看上去very nice啊,跑一下試試,

into A constructor

into B constructor

into C constructor

into A destructor

in D constructor catch: exception from C constructor

into B destructor

into C destructor

*** glibc detected *** ./a.out: free(): invalid pointer: ***

指針錯誤!同時我們可以發現在進入catch語句前基類A執行了析構函數,這說明到達catch語句時,已經跳出了構造函數的范圍,D和A的成員數據都已經是不可訪問的了。

C++為什麼要這樣做呢,為什麼構造函數體外的catch語句中無法訪問數據成員?

首先,無法知道b和c是否已經初始化了,刪除未初始化指針是非法的。

其次,我們假設可以知道b初始化了,c沒有初始化,我們要刪除b,如果catch中可以訪問b和c的話(我們做個假設),改變B的類型,使B包含一個A*成員數據,考慮下這種情況,

D() :A(), b( B(static_cast<A*>())), c((std::runtime_error &

A已經析構了,b的數據成員A已經不存在,這是很危險的。

c++認為,不管是基類還是數據成員構造出現失敗,那麼整個對象構造都是失敗的,不存在半成品。構造函數塊外的catch語句(上面這種)即使沒有顯示地重新拋出異常,c++也會自動拋出,一直到最下層派生類對象構造處停住。比如以上例子,catch沒有顯示throw,在main函數裡:

 (std::runtime_error &

仍然會捕捉到C構造函數拋出的runtime_error異常。

綜上,可以總結以下規則

1. 構造函數體外的try-catch語句只有一個用途——轉換捕捉到的異常對象

2. 必須在構造函數體內分配資源,不要在初始化列表中

3. 一定要用try-catch語句管理資源的話,在構造函數體內。

4. 使用RAII方式管理資源,這會少死亡很多腦細胞,像這樣子

<B><C> B()), c(

 歡迎討論

 

參考

http://www.gotw.ca/gotw/066.htm

《more effective c++》

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved