【问题标题】:How to free dynamic memory if exception occurs in constructor?如果构造函数中发生异常,如何释放动态内存?
【发布时间】:2019-10-12 05:36:21
【问题描述】:

我遇到了构造函数分配动态内存的情况,如果构造函数中发生任何异常,它并没有释放动态分配的内存。为了避免这种情况,我使用了 unique_ptr,它能够正确释放内存。

为了展示这里的情况是一个虚拟代码。

class ExceptionInConstructor
{
 unique_ptr<int> a;
public:
    ExceptionInConstructor()
    {
        a = std::unique_ptr<int>( new int(10));
        cout <<"Constructor called. Value of a is "<< *a<<endl;
        //some exception occurs after the mrmory allocation
        throw exception();
    }
    ~ExceptionInConstructor()
    {
        cout << "Dest called()"<<endl;
    }
};

int main()
{ 
    try
    {       
        ExceptionInConstructor ex; 
    }
    catch(...)
    {}  
    return 0;
 }

对于这种情况,这是一种正确有效的方法,还是对于这种情况有更好的选择?

编辑1:删除了错误留下的析构函数中的注释代码

【问题讨论】:

  • 这正是使用智能指针的目的。 “它没有释放动态分配的内存。”你是如何(哪个工具)观察到的?
  • ...和一般的 RAII 习语
  • 在您展示的特定情况下,没有必要。当抛出异常时,unique_ptr 的析构函数释放它管理的对象a 和动态分配的对象(来自new int (10))。就main()而言,一旦抛出异常,对象ex就永远不存在了。不过,通常认为在构造函数的初始化列表中初始化成员 a 比在构造函数主体中更好。
  • The rule of zeroRAII 很好地解决了这个问题。
  • @WhozCraig:OP 使用std::unique_ptr&lt;int&gt;(而不是unique_ptr&lt;int[]&gt;)(并按原样使用),所以看起来是有意的。

标签: c++


【解决方案1】:

不,这正是智能指针和一般RAII 的重点和预期用例。

还请注意,您的析构函数中的delete a 在任何情况下都是错误的,因为unique_ptr 本身不是指针。相应地,如果构造函数中出现异常,也不会调用析构函数。

【讨论】:

  • "delete a" 被错误地添加到没有智能指针的情况下,我将其删除。 @inf是的,我知道在构造函数中出现异常时不会调用析构函数。这就是为什么它没有释放分配给没有 uniqe_ptr 的 int 变量的内存的原因。
猜你喜欢
  • 2014-04-03
  • 2019-08-12
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-10
  • 2018-11-18
  • 2016-07-16
相关资源
最近更新 更多