【问题标题】:Throwing an exception in a constructor of a c++ class在 C++ 类的构造函数中抛出异常
【发布时间】:2017-02-09 13:02:52
【问题描述】:
下面的代码是否表示内存泄漏?
Test 类的析构函数没有被调用(屏幕上没有输出),我假设分配给 Int 类数组的所有内存都没有返回给系统?我的假设正确吗?如果发生异常,我应该如何收回在构造函数中分配的资源?
#include <iostream>
using namespace std;
class Int{
public:
int v;
Int(){
cout<<"inside Int constructor ..."<<endl;
}
~Int(){
cout<<"inside Int destructor ..."<<endl;
}
};
class Test{
public:
Int* a;
Test(){
a=new Int[10];
cout<<"inside Test constructor ..."<<endl;
throw(0);
}
~Test(){
delete [] a;
cout<<"inside Test destructor ..."<<endl;
}
};
int main(){
try{
Test T;
}
catch (int e){
cout<<"Error!!!"<<endl;
}
return 0;
}
【问题讨论】:
标签:
c++
memory-leaks
constructor
exception-handling
destructor
【解决方案1】:
没有调用析构函数,因为对象从未完全构造。在部分构造的对象上调用它可能更危险,因为它会尝试撤消从未完成的事情。作为程序员,您有责任确保在发生异常时不会从构造函数中泄漏内存(或任何其他资源)。
但是,基类和成员变量的析构函数会被调用!这就是为什么在大多数情况下最好依赖智能指针或容器,它们将为您处理资源管理。尝试像这样改变你的班级:
#include <memory>
class Test{
public:
std::unique_ptr<Int[]> a;
Test(){
a=std::make_unique<Int[]>(10);
cout<<"inside Test constructor ..."<<endl;
throw(0);
}
~Test(){
//no need to delete[] a;
cout<<"inside Test destructor ..."<<endl;
}
};
这是一个双赢的局面。你会看到Int的析构函数会被调用,你不需要手动处理内存。
【解决方案2】:
我想出了一个解决方案,但不确定这是一个好的设计还是正确的方法。你能评论一下吗?
#include <iostream>
using namespace std;
class Int{
public:
int v;
Int(){
cout<<"inside Int constructor ..."<<endl;
}
~Int(){
cout<<"inside Int destructor ..."<<endl;
}
};
class Test{
public:
Int* a;
Test(){
try{
a=new Int[10];
cout<<"inside Test constructor ..."<<endl;
throw(0); // exception is thrown
}
catch (int e){
delete [] a;
cout<<"Error!!!"<<endl;
}
}
~Test(){
delete [] a;
cout<<"inside Test destructor ..."<<endl;
}
};
int main(){
Test T;
return 0;
}