c ++非完全构造的对象释放

时间:2012-10-21 20:41:29

标签: c++ exception exception-handling

代码:

#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.


}

为堆中的A对象分配内存,将内存的地址传递给构造函数 但是当构造函数throw 1;然后类型为A的对象将不被视为完全构造的对象。所以不行 指针将返回指针p。如果我明白了什么不对,请随时纠正我。

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

2)当我在A函数内创建main类型的本地对象时怎么办?显然它也不会完全构建。何时取消分配此对象(在调用完全构建的子对象的析构函数之后)。

4 个答案:

答案 0 :(得分:5)

1)解除分配是为你完成的。

2)如果它是一个本地对象,它首先从未被分配过。

答案 1 :(得分:5)

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

答案 2 :(得分:4)

new A()完成的分配包含多个步骤:

  1. 使用operator new(sizeof(A))分配内存。
  2. 尝试默认在已分配的内存中构造一个对象。
  3. 当默认构造失败时,将使用之前获得的地址调用operator delete(x)
  4. 更一般地说,如果您使用重载operator new(),例如调用new(allocator) A()的{​​{1}}(其中operator new(size_t, Alloctor)可转换为allocator),则相应Allocator被称为。{/ p>

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

答案 3 :(得分:1)

在CPP中,构造函数(ctor)调用的顺序是:

  • 虚拟基类:虚拟基本ctor,根据深度第一序列调用。
  • 基类:基类定义类时根据派生声明调用序列。
  • 非静态成员对象
  • 派生类ctor;

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

CPP确保将释放完全构造的对象(Not Pointers)的资源。

有RAII(资源获取是初始化)。我们使用对象来包装原始指针以分配内存,然后在dtor中释放内存。如果派生对象由于(没有足够的内存,异常等)而部分构造,则将调用成员对象dtor。

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

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