2012-05-27 49 views
0
class A 
{ 
public: 
    int i; 
    ~A() 
    { 
     std::cout << "~A" << std::endl; 
    } 
}; 

class B: public A 
{ 
public: 
    int k; 
    ~B() 
    { 
     std::cout << "~B" << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    A* p = new B(); 
    delete p; 
    return 0; 
} 

上面不會導致內存泄漏雖然鹼析構函數不是虛擬和我知道的原因。這是未定義的行爲嗎?

但是這種未定義的行爲與否?

說也不會有內存泄漏如果派生類不指向其它動態數據,即使基地析構函數非虛擬?

回答

7

是的,它是。通過指向基類的指針刪除派生的class的對象,而不具有virtual析構函數是教科書UB。

5.3.5/3:

在第一種方式(刪除對象),如果靜態類型 操作數是從它的動態類型不同,靜態類型應是 基操作數的動態類型的類和靜態類型應具有虛擬析構函數或行爲未定義。在第二個備選 (刪除數組)如果動態類型的對象是從它的靜態類型 刪除不同的,那麼行爲是undefined.73)

由於它是未定義的行爲,它並沒有真正使感覺猜測代碼是否會泄漏。只是試圖修復代碼而不是預測結果。

+0

你有沒有遇到這樣的代碼(派生類不指向動態數據),導致漏氣? –

+0

@new_perl是的,但是派生類析構函數也釋放了一些內存。 –

+0

這肯定會發生。但我在談論派生類析構函數不需要明確釋放任何東西的情況。 –

4

是的,因爲靜態類型(這裏是A)與動態類型(在你的例子中爲B)不同,並且沒有virtual析構函數,所以它是UB。

5.3.5/2(在5.3.5/3 C++ 11):

在第一種方式(刪除對象),如果靜態類型的操作數是從它的動態類型不同,靜態類型應該是操作數的動態類型的基類,並且靜態類型應該具有虛擬的析構函數或行爲未定義。