2009-10-30 53 views
2

請參見下面的代碼和它的輸出 - 請解釋我的代碼異常處理代碼,請解釋一下

void abc(int); 

class A 
{ 
public: 
    A() 
    { 
     cout<<"Constructor Called"; 
    } 
    ~A() 
    { 
     cout<<"Destructor called"; 
    } 
}; 

int main() 
{ 
    try 
    { 
     abc(-1); 
    } 
    catch(int p) 
    { 
     cout<<p<<endl; 
    } 
    return 0; 
} 

void abc(int p) 
{ 
    A * Aptr = new A[2]; 
    if(p<0) 
     throw p; 
} 

輸出:

Constructor Called 
Constructor Called 
-1 

任何人都可以解釋爲什麼析構函數沒有被稱爲在正常堆疊展開的情況下

回答

10

該指針:

A * Aptr = new A[2]; 

是一個原始指針。當它超出範圍時,只有指針本身被銷燬 - 對它指向的數組沒有做任何事情。所以這個數組並不是delete[]',並且析構函數沒有被調用。這是內存泄漏的典型例子。

有是該問題三種典型的解決方案:

  • 在棧上分配數組本身
  • 使用std::vector
  • 使用智能指針(未std::auto_ptr - 它是不適合與陣列使用
+0

而典型的解決方案是? – 2009-10-30 16:32:30

0

難道是因爲你沒有在你的A類上調用delete?如果你沒有刪除dynamica lly分配的類未使用desnstructor。

0

因爲你在堆上分配。被釋放的是保存指向對象數組的指針的變量。不是物體本身。

0

aptr是一個堆分配變量,而不是堆棧變量。你需要顯式地刪除它,以便調用析構函數(並釋放內存)。

7

析構函數未被調用,因爲您分配的對象從不被刪除。如果您刪除了throw,則會得到相同的輸出。

如果,另一方面,你改變了你的函數到這一點:

void abc(int p) 
{ 
    A A_array[2]; 
    if (p<0) 
     throw p; 
} 

你會看到析構函數被調用。

0

如果你反而會做到這一點:

A a[2]; 

,而不是

A *Aptr = new A[2]; 

你會被調用析構函數。 你動態分配的任何東西,你將不得不釋放你自己。

0

您在堆上創建了該對象。刪除對象時析構函數將被調用。

如果你沒有在堆上創建對象,析構函數將按照你的預期調用。

6

如別處所述,C++指針不會刪除它們在超出範圍時指向的內存。你有幾個選擇:

  1. 困難的方法 - 嘗試和自己做內存管理。這種方式存在內存泄漏和緩衝區溢出。儘量不要這樣做。

    void abc(int p) 
    { 
        A * Aptr = new A[2]; 
        if(p<0) 
        { 
         delete [] Aptr; 
         throw p; 
        } 
        delete [] Aptr; 
    } 
    
  2. 把數組在棧上,讓正常的棧展開處理:

    void abc(int p) 
    { 
        A Aptr[2]; 
        if (p<0) 
         throw p; 
    } 
    
  3. 而不是使用原始指針指向新分配的數組中,持有使用它到智能指針類像scoped_arrayshared_array,或其他一些RAII類:

    void abc(int p) 
    { 
        boost::scoped_array<A> Aptr (new A[2]); 
        if(p<0) 
         throw p; 
        } 
    } 
    

2和3實際上是C++代碼中使用異常的唯一安全選項 - 如果使用原始指針和手動內存管理,遲早會導致內存泄漏。無論你多麼小心,異常安全代碼幾乎都需要RAII。

3

除了建議有關boost::shared_arrayboost::scoped_array你也可以只使用std ::向量:

std::vector<A> array(2); 
if(p < 0) 
    throw p; 

請注意,您的類型應該可拷貝,如果你走這條路線,但是,由於性病::矢量將在插入過程中或內部調整大小等時複製它們。