2014-09-21 62 views
3

我去了this文章 ,並且聲明構造函數拋出異常完成?有沒有內存泄漏?

注:如果一個構造函數拋出一個異常,與本身清理對象相關的內存 完成 - 沒有內存泄漏 。例如:

void f() 
{ 
X x; // If X::X() throws, the memory for x itself will not leak 
Y* p = new Y(); // If Y::Y() throws, the memory for *p itself will not leak 
} 

我難以理解這一點,將不勝感激,如果有人可以澄清這一點。我嘗試了下面的例子,它顯示了在構造函數中不會調用析構函數的例外情況。

struct someObject 
{ 
    someObject() 
    { 
     f = new foo();  
     throw 12; 
    } 
    ~someObject() 
    { 
     std::cout << "Destructor of someobject called"; 
    } 

    foo* f; 
}; 

class foo 
{ 
public: 
    foo() 
    { 
      g = new glue(); 
      someObject a; 
    } 
    ~foo() 
    { 
     std::cout << "Destructor of foo"; 
    } 
private: 
    glue* g; 
}; 


int main() 
{ 
    try 
    { 
     foo a; 
    } 
    catch(int a) 
    { 
     //Exception caught. foo destructor not called and someobject destrucotr not called. 
     //Memory leak of glue and foo objects 
    } 
} 

我該如何解決這個問題?

對不起,這可能是最新的版本。

+0

析構函數未被調用,因爲對象從未正確構造。 – 2014-09-21 18:58:04

回答

3

「...析構函數不會被調用。」

由於該對象不被視爲已構造,在構造函數失敗並出現異常之後,析構函數將不會被調用。

對象分配和構造(僅僅銷燬)是不同的東西。

在拋出異常之前使用new()分配的任何對象都會泄漏。

你不應該自己管理這些資源,除非你真的真的需要它,而且大概100%確定你正在做什麼。

相反地,對於來自standard dynamic memory management library的班級成員使用合適的智能指針。

+0

但不會有一個內存泄漏的膠水和foo對象 – Rajeshwar 2014-09-21 19:00:58

+0

感謝您的清除。再次抱歉更新可能造成的不便。 – Rajeshwar 2014-09-21 19:07:16

3

當構造函數拋出時,不會調用析構函數。當 異常構造函數中拋出有幾件事情, 你應該注意到在妥善處理,可能在 對象的中止施工已經發生資源 分配方面:

  • 的析構函數正在構建的對象將不會被調用。
  • 包含在該對象類中的成員對象的析構函數將被稱爲
  • 正在構建的對象的內存將被釋放。
+0

歡迎來到社區!您正在使用報價標記並鏈接到您的答案中的當前問題。可能鏈接和引用都不需要。您可以在答案下通過「編輯」鏈接編輯您的答案。 – 2014-09-21 19:15:19

+0

@ValentinP。謝謝,:)我編輯它! – 2014-09-21 19:19:35

+1

應該澄清的是,只有在拋出異常之前完全構造的成員纔會調用類成員的析構函數。在構造函數體內使用'new'分配的成員必須手動刪除,因爲它們的析構函數不會自動調用。這意味着捕捉異常,釋放內存,然後重新拋出異常。或者使用智能包裝來保存分配的內存,直到構造函數準備好正常退出。 – 2014-09-21 19:30:21