异常 class 复制构造函数

Exception class copy constructor

我正在通过使用用于抛出的 class 的复制构造函数来测试在执行堆栈展开调用 std::terminate 时抛出的方式。

根据 C++14 N4296 - §15.1.3:

Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).

class X
{
  public:

    X() = default;

    X(const X&)
    {
      throw std::runtime_error{"X copy constructor"};
    }
};

int main()
{
  try
  {
    throw X{};
  }
  catch(const std::exception& e)
  {
    std::cout << e.what() << std::endl; // this line gets executed, does not terminate
  }
  catch(const X& other)
  {
    std::cout << "X exception" << std::endl;
  }
}

为什么上面的代码没有调用std::terminate?我对上面代码的理解是try里面的throw X{}开始栈绕,然后调用copy constructor来调用handler,但是copy constructor也抛出异常。请注意,如果更改 throw X{} 的复制构造函数的抛出表达式,则它会终止。

直到异常对象被初始化,还没有抛出异常。因此,系统还没有开始做异常处理。

由于复制正在抛出异常对象,因此唯一成功执行的 throw 是复制构造函数中的对象。

As a note if change the copy constructor's throw expression for throw X{} then it terminates.

这实际上是无限递归导致的堆栈溢出。每次构造异常对象的尝试都会引发另一个异常和另一个构造异常对象的尝试。