2

代码 :

#include<iostream>
using namespace std;
class A{
    public:
    A(){cout << "A() Constructor " << endl;
        throw 1;
    }

};


int main(){
A* p=0;
cout << p << endl; // p value is 0
try{
p=new A(); // object is not fully constructed, no address is returned to p. for future deallocation

}
catch(...){cout << "Exception" << endl;}
cout << p << endl; // this will output that p has the value 0,proof that no address was returned to p.


}

为堆中的一个对象分配内存,内存的地址被传递给构造函数,但是当构造函数时throw 1;,类型的对象A不会被认为是一个完全构造的对象。所以没有指针会返回指针p。如果我理解错误,请随时纠正我。

问题:
1)所以我的问题是在这种情况下如何为 A 对象释放内存。我不是在谈论析构函数调用,而是内存的释放。

2)当我在函数A内部创建一个本地类型的对象时呢?main显然它也不会完全建成。这个对象什么时候被释放(当然是在调用完全构造的子对象的析构函数之后)。

4

4 回答 4

5

1) 解除分配已为您完成。

2)如果它是一个本地对象,它一开始就没有被分配。

于 2012-10-21T20:44:01.490 回答
5

当构造函数抛出为该对象分配的内存时,会自动释放,顺便说一句,不会调用析构函数。您不需要解除分配。

于 2012-10-21T20:46:06.907 回答
4

完成的分配new A()由多个步骤组成:

  1. 使用分配内存operator new(sizeof(A))
  2. 尝试在分配的内存中默认构造一个对象。
  3. 默认构造失败时,operator delete(x)使用之前获得的地址调用。

更一般地,如果您使用重载的operator new(),例如new(allocator) A()调用operator new(size_t, Alloctor)(其中allocator可转换为Allocator),operator delete()则调用对应的。

作为异常抛出的一部分,所有部分构造的子对象也被销毁(以它们构造的相反顺序)。也就是说,如果从对象的构造函数中抛出异常,您不需要关心清理(假设所有子对象都正确地照顾它们分配的资源)。这与对象是在堆上还是在堆栈上分配无关。

于 2012-10-21T20:49:38.473 回答
1

在 CPP 中,constructor(ctor) 调用的顺序是:

  • virtual base class:virtual base ctor,按照深度优先顺序调用。
  • 基类:定义类时根据派生声明调用基类的顺序。
  • 非静态成员对象
  • 派生类ctor;

以相反的顺序调用析构函数(dtor)。

CPP 确保完全构造的对象(非指针)的资源将被释放。

有 RAII (Resource Acquisition Is Initialization)。我们使用对象包装原始指针来分配内存,然后在 dtor 中释放内存。如果派生对象由于(内存不足、异常等)而部分构造,则将调用成员对象 dtor。

在上面的简单示例中,没有分配资源,因此没有资源泄漏。

但是如果有成员指针在 throw 之前分配内存,就会出现内存泄漏。如果我们将内存包装在一个类中,并将这个类的一个对象作为一个组件(使用 RAII),那么就不会有内存泄漏。

于 2014-06-04T12:32:05.133 回答