繁体   English   中英

面对异常时构造函数中的c ++可用内存分配

[英]c++ free memory allocation in constructor when facing exception

在构造对象时,我在异常的情况下发现了一些有趣的行为:

class bookentry
{
public:
    bookentry(){
      t1.reset(new test1);       //0 
      test1 *t11 = new test1;    //1
      test2 *t22 = new test2;    //2
      throw 1;                   //3
    }
protected:
private:
  auto_ptr<test1> t1;
  auto_ptr<test2> t2;
};

从我测试的:

如果我们从test2的构造函数(#2)抛出异常,那么

  1. t1 :将被完全销毁,即调用t1的析构函数,并释放内存。
  2. t11 :永远不会被销毁(既不会调用t11的析构函数也不会释放内存)。
  3. t22 :这很有趣,t22的析构函数不会被调用,这是正确的,但t22的内存将被释放!

如果我们从bookentry的构造函数(#3)抛出一个异常,这次,事情就会变得不同了: t22永远不会被破坏(既不会调用t22的析构函数也不会释放内存),t11与上面相同

我只是对#2的句子感到困惑

test2 * t22 = new test2; // 2

似乎当我们从类构造函数抛出一个异常时,new表达式将确保调用相应的delete, 但是在该异常之前通过new表达式完全创建的任何对象都将被泄露(如果我们抛出一个t11或t11和t22) #3处的例外情况。

所以,如果我们编写如下代码并且第5个对象构造失败:

test2 * t2s = new test2 [10];

那么,它似乎是一个更安全的垃圾:

  1. 已经构建的对象将被销毁,
  2. 记忆将被释放。

我的问题是,这是标准的c ++行为吗? 我只是测试msvc 2012和gcc 4.4.6,两者都看起来实现了这样的机制。

编辑以使我的问题更清楚:

在某些情况下,您需要在其他正常函数中编写类似t1.reset(new test1)[在我的代码中参见#1]的代码。 在这种情况下,如果从构造函数抛出异常。 我如何推断程序状态? 有内存泄漏吗?

我的测试确保在这种情况下这些没有内存泄漏,但它是标准的c ++行为吗?

规则很简单:
在该范围内完全创建的所有对象都将被销毁
上述规则不适用于指向动态存储上分配的对象的原始指针( 使用new分配 )。 他们需要明确delete d。 使用new您明确拥有资源管理,调用delete以释放资源是您的工作,编译器不会为您执行此操作。


好读:

构造函数失败 - Herb Sutter


请注意,在C ++中管理资源的最佳方法是使用RAII和智能指针。 在构造函数中更是如此。 不使用任何原始指针,只需将它们包装在智能指针中,并且在出现此类异常时,它们将自动为您的对象执行资源管理。 当您在代码示例中使用auto_ptr而不是原始指针时,您刚刚体验过这种能力。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM