代码:
#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
类型的本地对象时怎么办?显然它也不会完全构建。何时取消分配此对象(在调用完全构建的子对象的析构函数之后)。
答案 0 :(得分:5)
1)解除分配是为你完成的。
2)如果它是一个本地对象,它首先从未被分配过。
答案 1 :(得分:5)
当构造函数抛出时,为该对象分配的内存会自动释放,但不会调用析构函数。你不需要解除分配。
答案 2 :(得分:4)
new A()
完成的分配包含多个步骤:
operator new(sizeof(A))
分配内存。operator delete(x)
。更一般地说,如果您使用重载operator new()
,例如调用new(allocator) A()
的{{1}}(其中operator new(size_t, Alloctor)
可转换为allocator
),则相应Allocator
被称为。{/ p>
作为异常抛出的一部分,所有部分构造的子对象也被破坏(按照构造它们的相反顺序)。也就是说,如果从对象的构造函数抛出异常,则不需要关心清理(假设所有子对象都正确地查看它们已分配的资源)。这与对象是在堆还是堆栈上分配无关。
答案 3 :(得分:1)
在CPP中,构造函数(ctor)调用的顺序是:
以相反的顺序调用析构函数(dtor)。
CPP确保将释放完全构造的对象(Not Pointers)的资源。
有RAII(资源获取是初始化)。我们使用对象来包装原始指针以分配内存,然后在dtor中释放内存。如果派生对象由于(没有足够的内存,异常等)而部分构造,则将调用成员对象dtor。
在上面的简单示例中,没有分配资源,因此没有资源泄漏。
但如果有成员指针在throw之前分配内存,则会出现内存泄漏。如果我们将内存包装在一个类中并将该类的对象作为一个组件(使用RAII),那么就不会有内存泄漏。