是否可以同时有两个或多个活动异常?

Is it possible to have two or more active exceptions at the same time?

C++17引入了一个新函数std::uncaught_exceptions:

Detects how many exceptions have been thrown or rethrown and not yet entered their matching catch clauses.

以下代码:

#include <iostream>

using namespace std;

struct A
{
    ~A()
    {
        cout << std::uncaught_exceptions() << endl;
    }
};

int main()
{
    try
    {
        try
        {

            A a1;
            throw 1;
        }
        catch (...)
        {
            A a2;
            throw;
        }
    }
    catch (...)
    {
        A a3;
    }   
}

输出:

1

1

0

是否可以同时有两个或多个活跃异常?

有例子吗?

是的。从因堆栈展开处理另一个异常而调用的析构函数中抛出异常:

struct D
{
  ~D()
  {
    std::cout << std::uncaught_exceptions() << std::endl;
  }
};

struct E
{
  ~E()
  {
    try
    {
      D d_;
      throw 2;
    }
    catch(...)
    {
      std::cout << std::uncaught_exceptions() << std::endl;
    }
  }
};

int main()
{
  try
  {
    D d;
    E e;
    throw 1;
  }
  catch(...)
  {
  }
}

d 的析构函数将在 1 仍然是活动异常时被调用。所以 std::uncaught_exceptions() 里面 ~d 将是 1.

对于e,其析构函数将被调用,而1是一个活跃的异常。它的析构函数将被调用。它会构造一个D,然后再次抛出。但是由于此时 12 都没有被捕获,所以 ~d_ 内部的 std::uncaught_exceptions() 将是 2.

std::uncaught_exceptions 的全部目的就是检测这种情况。它可以让您知道对象是由于堆栈展开还是通过正常执行而被销毁。这让您知道是否应该进行不同类型的清理。考虑一个 RAII 对象,如果它由于堆栈展开而被销毁,它将回滚事务。