作者purpose (purpose)
看板C_and_CPP
標題Re: [問題] delete [] 順序?
時間Thu May 17 09:08:43 2012
> ctor 比較早 dtor 會比較晚
上面說的是如果有 n 個類別,且其中 n1 類別的 ctor 最早被呼叫,
則 n1 類別的 dtor 就會最晚被呼叫。
很多文件、書本講到建構、解構順序時,都會分析這兩種狀況:(1) 繼承 (2) 類別成員
比如,動物類->狗類->奶油犬類
在這樣的繼承關係下,我們可以說,奶油犬類存在的前提是,有狗這個類別,
而狗類存在的前提又是有動物這個類別。
因此沒有人依賴最 derived 的類別: 奶油犬類
所以如果上帝要毀滅一個物種,最應該被拿來開刀的,應該是奶油犬。
故可知,奶油犬類的 dtor 理當最早執行,接著才輪到狗類,最後才能輪到動物。
就因為動物類這麼重要,所以其 ctor 最早執行。
--
至於類別成員的建構、解構順序,之所以常被關注,是因為容易搞錯。
class 螢幕繪圖 {
private:
長方形類 rect;
圓型類 cr;
public:
螢幕繪圖 : cr(2), rect(2, 3) {
// ...
}
};
上面這個類別的建構式中,使用了 "初值器",看起來好像圓形類的 ctor 會先執行,
但其實是長方形類的 ctor 先執行,因為順序是看該成員在螢幕繪圖別中,
誰先被宣告的,以此例來說,先宣告的是這行「長方形類 rect;」
通常類別成員之間的順序,沒有繼承關係下的順序重要,但就像 C++ Primer 舉的
例子一樣,如果你初始化時這樣寫 rect(cr) 把比較晚建構的 cr 拿來用那就有問題。
也可能 rect 在執行 ctor 時會在螢幕上畫一個長方形圖案,而 cr 跑 ctor 時
也會在螢幕上畫圓形圖案,在兩者都畫圖的情況下,誰先畫就很重要了,
因為比較早畫的圖有可能被後面的圖案覆蓋。
--
回到原 PO 的案例
p = new CFoo[3];
delete [] p;
該陣列有 3 個 CFoo 物件,既然是相同類別,那就不像繼承的狀況可以看出
相依關係。
如果能確定建構順序為 elem0 -> elem1 -> elem2
那解構時,或許順序選 elem2 -> elem1 -> elem0 是比較保險的。
問題是:有規定陣列內的元素,一定要從記憶體位址靠前的先建構?
好像沒聽過...大家都是同質的東西,憑什麼不能 elem2 先呢?
這寫法還是能免則免吧
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.143.166
→ diabloevagto:我記得在class內的參數建構順序是依照上到下 05/17 09:39
→ diabloevagto:而不是initialization list順序對吧? 05/17 09:40
→ diabloevagto:我在寫都盡量將兩者的順序相同 05/17 09:41
→ purpose:您說的是,上文想表達的就是這個意思,我寫得很不清楚歹勢 05/17 09:42
→ xatier:明白了!概念變得好清楚!!!謝謝 p 大用心 05/17 09:42
→ diabloevagto:Effective C++裡面有一章特別在講這個部份 05/17 09:44
→ diabloevagto:看了有一段時間有點忘記是那章節了 05/17 09:45
推 damody:推精采講解,如果要同類解構控制直接用for loop來delete 05/17 10:17
推 damody:等一下,奶油犬根本不是動物種類呀!!為什麼會繼承狗XXD 05/17 10:19
公子請明察
奶油犬
http://www.youtube.com/watch?v=o61JARR1hP0
奶油獅
http://www.butterlion.com.tw/
奶油小生
http://addons.books.com.tw/G/editor/author/2003091501.jpg
※ 編輯: purpose 來自: 124.8.143.166 (05/17 10:29)
→ diabloevagto:怎麼變成奶油犬了... 05/17 10:49
推 xatier:XDDDDDDDDDDDD 05/17 12:29
推 legendmtg:奶油犬XDDD 05/17 13:14
推 raincole:我記得那個member順序不一致會報警告 XD 05/17 14:05
→ xatier:好像要開一些 warning flags 才會噴(? 05/17 17:00
推 lwecloud:奶油獅更不是狗阿XDDDDD 05/17 17:43