在数组创建期间,在C++中抛出未捕获的异常时,为什么不调用析构函数?

pav*_*din 5 c++ destructor exception try-catch

class XX
{
public:
    static unsigned s_cnt;
    XX()
    {
        ++ s_cnt;
        std::cout << "C XX " << s_cnt << "\n";

        if ( s_cnt > 2 )
            throw std::exception();
    }

    //private:
    ~XX()
    {
        std::cout << "~ XX\n";
    }
};
unsigned XX::s_cnt = 0;

int main()
{
    try
    {
        XX *xx = new XX[10];
    } catch ( ... )
    {
        std::cout << "Exc\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

C XX 1
C XX 2
C XX 3
~ XX
~ XX
Exc
Run Code Online (Sandbox Code Playgroud)

但当我删除try-catch时,我看到:

C XX 1
C XX 2
C XX 3
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
zsh: abort      ./a.out
Run Code Online (Sandbox Code Playgroud)

为什么C++在第一种情况下调用析构函数而不在第二种情况下调用析构函数?

Seb*_*edl 14

当你没有捕获异常(即它成为一个未捕获的异常并终止你的程序)时,C++并没有给你任何实际调用析构函数的保证.

这为编译器提供了如何实现异常处理的余地.例如,GCC首先搜索处理程序.如果找不到,则立即中止,保留完整的堆栈信息以进行调试.如果确实找到了一个,它实际上展开堆栈,销毁对象,直到它到达处理程序.这就是你没有看到输出的原因:程序在销毁任何对象之前中止.