构造函数作为函数 try 块 - 异常中止程序

Constructor as a function try block - Exception aborts program

本文关键字:异常中止 程序 try 函数 构造函数      更新时间:2023-10-16

我不确定这是编译器的问题还是我做错了什么。我正在使用Visual Studio 2013编译器。

我有一个类,我需要在我的构造函数初始值设定项列表中获取大量资源,其中大多数资源可能会引发异常。我将成员初始值设定项列表包装在一个函数 try 块中,并在那里捕获了异常。但是即使 catch 子句没有重新引发异常,我的程序仍然中止。我不允许发布实际代码。所以我用这个等效的演示代码重现了这个问题。有人可以帮我解决这个问题吗?

#include <iostream>
using namespace std;
class A{
public:
    A() try : i{ 0 }{ throw 5; }
    catch (...){ cout << "Exception" << endl; }
private:
    int i;
};

int main(){
    A obj;
}

在执行此代码时,我收到一个窗口警报"abort() 已被调用"。所以我想系统将其视为未捕获的异常并调用 terminate()。

另一方面,如果我将 main() 中的对象构造包装在 try-catch 块中,那么异常就会被正确捕获并且程序正常终止。

有人可以告诉我我是否在这里做错了什么吗?

有一个相关的问题

http://gotw.ca/gotw/066.htm

基本上即使你不扔进你的 catch 块,异常也会自动重新抛出

如果处理程序主体包含语句 "throw;",则 catch 块显然会重新抛出 A::A() 或 B::B() 的任何异常 排放。不太明显,但在标准中明确说明的是 如果 catch 块没有抛出(要么重新抛出原始块 异常,或抛出新的东西),并且控制到达 捕获构造函数或析构函数的块,然后是原始块 自动重新引发异常。

根据函数try块的 cppreference.com 文档,这是正常行为:构造函数或析构函数上的所谓函数try块必须从其catch子句中抛出,否则在catch子句之后会隐式重新抛出。

这是完全有道理的:对象A尚未正确构造,因此不处于适合使用的状态:它必须抛出异常。您必须确保构造对象的位置是否成功,即在 main() 中的示例

在构造函数function-try-block中无法捕获异常。

N3376 15.2/15

如果控制到达末尾,则会重新引发当前处理的异常 构造函数或析构函数的函数尝试块的处理程序。

您应该在对象创建位置捕获它。

我建议你阅读文章:"GotW #66 Constructor Failures"在网站上:http://gotw.ca/gotw/066.htm