为什么析构函数在抛出异常时调用了两次?

时间:2011-06-23 15:26:27

标签: c++

我很困惑为什么在抛出excpetion时会调用两次destrctor以及它们被调用哪一点?

#include <iostream> 
using namespace std;
class base
{
 public:
     base(){cout<<"constructor called"<<endl;}
     ~base(){cout<<"destructor called"<<endl;}
};
void fun()
{
     throw base(); //<=- Create temp obj of base, and throw exception

}
int main()
{
    try
    {
        fun();
    }
    catch(...)
    {
        cout<<"handle all exception"<<endl;
    }

}

以下是输出

constructor called
destrctor called
handle all exception
destuctor is called

但是当我添加了复制构造函数时,它从未调用但只调用了析构函数一次所以发生了什么????

#include <iostream> 
using namespace std;
class base
{
 public:
     base(){cout<<"constructor called"<<endl;}
     ~base(){cout<<"destructor called"<<endl;}
     base (base &obj){cout<<"copy constructor called"<<endl;}
};
void fun()
{
     throw base(); //<=- Create temp obj of base, and throw exception
}
int main()
{
    try
    {
        fun();
    }
    catch(...)
    {
        cout<<"handle all exception"<<endl;
    }

}

输出:

constructor called
handle all exception
destrctor called

3 个答案:

答案 0 :(得分:7)

因为异常对象是在catch中复制的。使用catch (base&v)按引用获取,而不是值。

答案 1 :(得分:7)

编译器可以根据需要多次复制您的异常对象。析构函数被调用两次,因为它有一个副本。

答案 2 :(得分:1)

因为catch块获取原始对象的副本。

要避免复制,请将try-catch写为:

try
{
    fun();
}
catch(const base &e)
{
    cout<<"handle all exception"<<endl;
}

我也想对设计发表评论:用户定义的异常类应该来自std::exception或其派生类之一。