【问题标题】:How to free resources when initializing list throws exception in c++?c++ - 初始化列表时如何释放资源引发异常?
【发布时间】:2021-07-25 07:02:58
【问题描述】:

在下面的代码中,我没有看到 A 或 C 的析构函数被调用。我知道我可以使用智能指针等,但一般来说,当初始化列表抛出时,我们应该如何处理已经分配的资源?


#include <iostream>

using namespace std;

class C
{
public:
  ~C ()
  {
    cout << "destructing C" << endl;
  }
};

class A
{
public:
  A ()
  {
    throw bad_alloc ();
  }
   ~A ()
  {
    cout << "destructing A";
  }
};

class B
{
public:
  B () try:pc (new C ()), pa (new A ())
  {
  }
  catch (...)
  {
    cout << "bad thing happened" << endl;
    throw;
  }


  A *pa;
  C *pc;
};

int
main ()
{
  try
  {
    B b;
  } catch ( ...)
  {
    cout << "i'm catching this bad here" << endl;
  }
  cout << "Hello World" << endl;

  return 0;
}

是否保证有泄漏?如果是这样,最好在构造函数主体中分配,然后在异常处理程序中删除?

【问题讨论】:

  • 你需要在B中添加析构函数
  • @AlanBirtles:在这个问题的上下文中,由于预期构造函数会抛出异常,因此仍不会调用析构函数(即使它已显式定义)。

标签: c++ exception


【解决方案1】:

最佳做法是按照您在问题中的建议使用智能指针。例如:std::unique_ptrstd::make_unique

class B {
 public:
  B() : pc(std::make_unique<C>()), pa(std::make_unique<A>()) {}

  std::unique_ptr<C> pc;
  std::unique_ptr<A> pa;
};

在这段代码中,如果pa 抛出,pc 的析构函数仍会被调用。

【讨论】:

  • 那么如果我们使用原始指针,这里肯定会有泄漏吗?
  • @JingmingZhang 你可以使用原始指针(智能指针没有什么神奇之处;他们已经这样做了),但你最终不得不重新发明智能指针为你处理,所以最好只使用智能指针。
  • @JingmingZhang 我能看到的使用原始指针的唯一出路是相当丑陋的:我们可以将所有指针(但最多一个)初始化为nullptr,然后在构造函数体中执行分配,我们可以在这里检查和处理异常。如果可能的话,我会尝试改用unique_ptrs。
猜你喜欢
  • 1970-01-01
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多