2014-09-21 64 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