不要用多型方式處理陣列以及陣列的析構

2021-08-25 18:46:09 字數 942 閱讀 4053

今天jackxu貼了一段**說有乙個奇怪的崩潰,希望一起看看,於是一研究了一下,**如下,coredump崩潰的地方在delete,編譯器是gcc 4.1.2版本。同時在visual studio 上,這個沒有錯誤。崩潰前也沒有任何輸出。

#include

class base

};

class parent: public base

};

int main()

初看了半天沒有發現問題。後來貼到群裡,讓大家看。幾個小夥子提醒是base* p = new test[2]; 導致的問題,我居然想了半天為啥不准這樣用呢。(快一年沒有寫c++**了,反映有點遲鈍,丟人顯眼了)。

經過多方提醒,才突然想起了這樣的base類的指標在++處理過程中應該是有問題的,因為指標無法知道自己應該塑形成子類指標,結構就會導致delete 了乙個無效的位址,導致崩潰。其實more effective c++對這個問題是有說明的。詳見條款3,不要用多型處理陣列。c++語言規格說,通過base類指標刪除乙個由dreived class 物件構成的陣列,結果未定義。

反饋給jack,jack又提出如果delete第二個位置的指標導致崩潰,為啥一行列印資訊沒有輸出,回頭看看**發現,的確是,如果第乙個變數已經析構,那麼就應該base::~base 就應該得到輸出呀。sriver用**輸出給出了析構順序,發現陣列是從後面開始呼叫析構函式的。先以為這個是編譯器自己的實現導致的,google了一下,發現這個倒是c++標準,陣列構造函式呼叫的時候順序呼叫,析構的時候,反向呼叫。由於gcc的實現,base指標指向的陣列最後乙個位置就是錯誤的,所以還沒有任何輸出就崩潰了。

感謝yunfeiyang, liangfeng , sriverxiao, kliu , djiang等同事,每次c++的多型析構總能讓我栽跟頭,而且很多事情只有在栽了跟頭才回真正記得牢。

2023年3月31日星期四,又開始回頭看點技術的東西

不要用多型方式處理陣列

基類中過載運算子 有乙個專用來處理基類物件的函式 如果對這個函式傳入的引數是單個物件,那麼通常情況下這個函式可以接收基類物件,也可以接收派生類物件,這是c 的多型特性決定的 但是如果這個函式處理的是物件陣列,因為指標算數表示式的工作原理,這個函式只能用來處理基類物件陣列,雖然在函式形式上也可以接收派...

不要以多型方式處理陣列

class bst class balancebst public bst vvoid printbstarray ostream s,const bst array,int numelements for int i 0 i numelements i s編譯器必須能夠有能力決定陣列中物件的大小。...

不要對陣列使用多型

不要對陣列使用多型 類繼承的最重要的特性是你可以通過基類指標或引用來操作派生類。這樣的指標或引用具有行為的多型性,就好像它們同時具有多種形態。c 允許你通過基類指標和引用來操作派生類陣列。不過這根本就不是乙個特性,因為這樣的 幾乎從不如你所願地那樣執行。假設你有乙個類bst 比如是搜尋樹物件 和繼承...