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

why destructor called twice when exception is thrown?

本文关键字:两次 函数调用 抛出异常 析构 为什么      更新时间:2023-10-16

我很困惑,为什么在抛出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

编译器可以随心所欲地复制异常对象。析构函数被调用两次,因为存在副本。

因为异常对象是在catch中复制的。使用catch (base&v)通过引用而非值进行抓取。

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

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

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

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