在构造函数中捕获异常

时间:2011-10-10 07:39:13

标签: c++ exception-handling

以下示例留下可能的内存泄漏,因为析构函数不会针对在其构造函数运行期间处理异常的对象运行。我在哪里处理这个内存泄漏?

#include <exception>

class MyClass {

public:
       MyClass() 
       {
           c = new char[5];
           throw std::runtime_error("test");
       }

      ~MyClass ()
       {
           delete[] c;
       }

private:
    char *c;
};

int main()
{
    try 
    {
        MyClass Obj;

    } 
    catch (std::runtime_error)
    {

    }
}

4 个答案:

答案 0 :(得分:6)

在构造函数中捕获异常,整理(释放内存),然后在没有内存泄漏的情况下抛出异常。

答案 1 :(得分:5)

最好使用 RAII ,在这种情况下,智能指针是具体的。

或者,您可以使用 Two Phased Construction 策略。

您始终可以在构造函数体内使用封闭的try-catch块,并为您动态分配的所有资源显式调用delete,但要考虑动态分配n个资源的场景,它在catch中明确跟踪需要解除分配的每个资源变得非常麻烦,在这种情况下,RAII为您提供了最佳解决方案,因为每个资源都隐含地负责自己的释放和你不需要有跟踪每个资源的开销。

boost::scoped_ptrstd::tr1::scoped_ptr适用于此方案而非任何原始指针。

答案 2 :(得分:4)

一种方法是在构造函数的开头throw条件异常,然后分配内存。

  MyClass() 
  {
     if(<condition>)
       throw std::runtime_error("test");
     c = new char[<SIZE>];
  }

其他方法是使用包含构造函数的特殊try-catch()语法:

MyClass() 
  try {
    c = new char[5];
    throw std::runtime_error("test");;
  }
  catch(std::runtime_error e) {
    delete[] c;
  }

Demo

答案 3 :(得分:1)

您可以在构造函数体中捕获异常,执行所需的清理,然后使用throw;重新抛出异常

也就是说,内存的异常和手动处理不能很好地结合在一起。使用自动管理c成员内存的对象(例如std::stringstd::vector<char>std::unique_ptr<char[]>等)会更好。如果您正在编写类似于上述类之一的类,那么您实际上只需要显式地管理内存,其目的正是为了照顾该内存。