概述
C++构造函数失败后,其对应的析构函数会被自动调用吗?
答案是不会。
能在构造函数中抛出异常,然后在外面捕获吗?
可以,但不建议这样做。C++之父和herb sutter这样的最顶级专家建议不要把容易出错的代码放在构造函数中,当然如果非要在构造函数做一些容易失败的事,那就在构造里throw异常吧。另外对于析构函数,Herb Sutter在Exceptional c++ 中也说过说:“永远都不要写能够抛出异常的析构函数” [1]。
所以综上,我们写代码时,还是最好不要把易出错的代码写在构造函数里了,我们加个init函数,构造成功后再init,与init对应的还要有个exit函数。
代码示例1:抛出异常后,delete将不不被执行,将造成内存泄漏。
#include <iostream>
void remodel(std::string & str)
{
std::string * ps = new std::string(str);
if (true)
throw "test exception";
str = *ps;
delete ps;
return;
}
void main()
{
remodel(std::string("abcde"));
}
智能指针和异常处理
我们可以使用智能指针和异常处理来防止内存泄漏。
#include <iostream> //[2]
#include <string>
#include <memory>
class report
{
private:
std::string str;
public:
report(const std::string s) : str(s) {
std::cout << "Object created.\n";
}
~report() {
std::cout << "Object deleted.\n";
}
void comment() const {
std::cout << str << "\n";
throw "test exception";
}
};
int main()
{
{
report *ps = NULL;
try
{
ps = new report("using auto ptr");
ps->comment();
}
catch (...)
{
std::cout << "test" << std::endl;
if (ps)
{
delete ps;
ps = NULL;
}
}
}
{
std::auto_ptr<report> ps(new report("using auto ptr"));
try
{
ps->comment();
}
catch(...)
{
std::cout << "test" << std::endl;
}
}
#if 0
{
std::shared_ptr<report> ps(new report("using shared ptr"));
ps->comment();
}
{
std::unique_ptr<report> ps(new report("using unique ptr"));
ps->comment();
}
#endif
return 0;
}