php建構函式裡丟擲異常 建構函式失敗 丟擲異常

2021-10-13 08:02:21 字數 1316 閱讀 8681

網上比較經典的總結:

什麼函式都有可能失敗,建構函式也不另外,比如new乙個物件或空間不成功。當建構函式失敗的時候,其實很多時候我們不想這個物件被繼續生成,這個時候就可以在建構函式裡面丟擲異常。c++規定建構函式丟擲異常之後,物件將不被建立,析構函式也不會被執行,但已經建立成功的部分(比如乙個類成員變數)會被部分逆序析構,不會產生記憶體洩漏。但有些資源需要在丟擲異常前自己清理掉,比如開啟成功的乙個檔案,最好關閉掉再丟擲異常(雖然系統也會把這個資源**),因為丟擲異常之後析構函式不會被執行了。

(1) c++中通知物件構造失敗的唯一方法那就是在建構函式中丟擲異常;(這句話並不是說我們只有這個方法才能讓上層知道建構函式失敗,雖然建構函式沒有返回值,我們完全可以在建構函式中傳入乙個引用值,然後在裡面設定狀態,執行完建構函式之後任然可以知道是否失敗,但這種情況下面物件其實還是被構造出來的,只是裡面有資源分配失敗而已,並且析構函式還是會執行。這和我們構造失敗不生成物件的初衷不符。)

(2) 建構函式中丟擲異常將導致物件的析構函式不被執行;(但已經生產的部分成員變數還是會被逆向析構的)

(3) 當物件發生部分構造時,已經構造完畢的子物件將會逆序地被析構;

網上的乙個栗子:

乙個例項物件的構造:

第一步,分配足夠的記憶體,如果失敗就是棧溢位或丟擲std::bad_alloc的異常,所以在這步你不用擔心記憶體洩露,而且這一步你是不能插手的,如果這步成功,就進入第二步。

new運算子的實現保證了記憶體洩漏不會發生。例如

t *p = new t;

將被編譯器轉換給類似下面的樣子:(其實和我們自己釋放已經申請的資源的思想流程是一樣的)

//第一步,分配原始記憶體,若失敗則丟擲bad_alloc異常

trycatch(...)

第二步,呼叫建構函式,在通常情況下,如果建構函式為空或沒有進行動態記憶體分配,你就不用關心記憶體洩露了

你需要關心的是建構函式中有動態記憶體分配

classa

catch(bad_alloc)~a()

;intmain()

a*pa=null;trycatch(bad_alloc){

cout<

delete pa;return 0;

pa是用null初始化的,即使在給a分配記憶體時(第一步)失敗,也不會導致後面的delete pa出錯。

對於建構函式可能失敗的做法一般有兩種

1. 在建構函式中丟擲異常,本物件構造未完成,它的析構函式不會被呼叫。當然,我們有義務釋放已經分配到的資源。簡單,最常見。

2. 把資源的初始化工作放在另乙個單獨函式中,比如 bool init(...),由物件建立者(比如工廠方法)先呼叫建構函式,再呼叫init方法。atl中常見。

建構函式裡丟擲異常 c 可否同時丟擲兩個異常

c 可否同時丟擲兩個異常 wcy123.github.io在 c 中,如果我們丟擲異常後 在捕獲異常之前,會析構掉所有還在堆疊上的物件。include using namespace std class object object object void foo catch const except...

建構函式中丟擲的異常

建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程 析構函式的執行 可誰能保證物件的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好自己...

建構函式中丟擲的異常

標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程 析構函式的執行 可誰能保證物件的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好自己。物件總是由不斷的繼承或不...