通过使用用于抛出,抛出的类的复制构造函数,我正在测试堆栈展开调用std::terminate
时的抛出方式。
Per C ++ 14 N4296 - §15.1.3:
抛出异常copy-initializes(8.5,12.8)一个临时对象, 称为异常对象。临时是一个左值,习惯了 初始化匹配处理程序中声明的变量(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
?我对上面的代码的理解是throw X{}
中的try
启动堆栈循环,然后调用复制构造函数来调用处理程序,但复制构造函数也会抛出。作为注释,如果更改throw X{}
的复制构造函数的throw表达式,则它将终止。
答案 0 :(得分:4)
在初始化异常对象之前,尚未抛出任何异常。因此,系统尚未开始进行异常处理。
由于副本正在抛出,并且初始化异常对象的原因是,成功执行的唯一throw
是复制构造函数中的那个。
作为注释,如果更改复制构造函数的throw X {}的throw表达式,则它会终止。
由于无限递归,它实际上是一个堆栈溢出。每次构建异常对象的尝试都会引发另一个异常,并引发另一个构造异常对象的尝试。