函数异常规范和标准异常-foo()抛出(异常) 在C++中,你可以用这样的异常规范声明函数: int foo() const throw(Exception); class ExceptionFileType { virtual const char * getError() const = 0; }; class ExceptionFileTypeMissing : public ExceptionFileType { virtual const char *getError() cosnt { return "Missing file"; } }

函数异常规范和标准异常-foo()抛出(异常) 在C++中,你可以用这样的异常规范声明函数: int foo() const throw(Exception); class ExceptionFileType { virtual const char * getError() const = 0; }; class ExceptionFileTypeMissing : public ExceptionFileType { virtual const char *getError() cosnt { return "Missing file"; } },c++,exception,exception-handling,throw,C++,Exception,Exception Handling,Throw,我发现了这两个链接: 及 但有几件事最终没有答案 问题1:为什么要添加异常规范?它会带来性能提升吗?编译器会有什么不同?因为在我看来,它就像是程序员的信息 问题2:如果我抛出不符合规范的东西,会发生什么(应该发生什么)?例如: int foo() throw(int) { throw char; // Totally unrelated classes, not types in real } 问题3:函数/方法不应抛出任何内容。我找到了至少两种(三种,不同编译器的可选语

我发现了这两个链接:

但有几件事最终没有答案

问题1:为什么要添加异常规范?它会带来性能提升吗?编译器会有什么不同?因为在我看来,它就像是程序员的信息

问题2:如果我抛出不符合规范的东西,会发生什么(应该发生什么)?例如:

int foo() throw(int) {
        throw char; // Totally unrelated classes, not types in real
}
问题3:函数/方法不应抛出任何内容。我找到了至少两种(三种,不同编译器的可选语法)方法来指定无异常抛出:

  • intfoo()throw()
  • gcc的
    int foo()
  • int foo()nothrow
    用于visual C++
哪一个是“正确的”?有什么区别吗?我应该用哪一个

问题4:“标准异常”、
错误分配
错误演员
错误异常
错误类型ID
ios\u基本故障

Ok
bad\u alloc
是自我解释的,我知道如何(更重要的是何时)使用它(添加到异常规范),但是其他的呢?他们中没有一个真的能打动我的心。。。它们与哪些“代码块”相关?Like
bad\u alloc
新字符[500000]
关联

问题5:如果我有异常类层次结构,如下所示:

int foo() const throw(Exception);
    class ExceptionFileType {
             virtual const char * getError() const = 0;
    };

    class ExceptionFileTypeMissing : public ExceptionFileType {
            virtual const char *getError() cosnt {
                    return "Missing file";
            }
    }
我应该使用:

    int foo() throw(ExceptionFileType);
或:


注意:带参考资料的答案会很好。我正在寻找良好的实践技巧。

中对问题1和2进行了详细介绍

问题3和5包含在该问题的公认答案中,建议您根本不使用异常规范

问题4似乎是通过将这些异常名称键入你所选择的搜索引擎或咨询一个好的C++书籍的索引而得到充分解决的。您对它们有什么特别的疑问吗?

简单的“良好实践”提示是:不要使用异常规范

本质上,唯一的例外是可能出现空的异常规范:
throw()
。这非常有用,因为在C++11中,它有自己的关键字(
noexcept
)。人们普遍认为,任何非空异常规范都是一个糟糕的想法

异常规范(除了
noexcept
)已被正式弃用——与许多弃用的特性不同,删除它对源代码的影响很小,因此我认为它很有可能最终被删除(当然不保证,但无论如何,这是一个相当公平的机会)


至于当/如果抛出异常规范不允许的类型的异常时会发生什么:
std::unexpected()
被调用。默认情况下,调用
terminate()
。您可以使用
std::set\u unexpected
来设置自己的处理程序——但您可以合理地做的只是在
terminate()之前添加一些日志记录。不允许您的意外处理程序返回。

首先,让我们非常清楚异常规范的作用:它是 或多或少像一个不能被禁用的
assert
,断言您 如果出现异常其他异常,则不会退出该功能 丢失的因此,它的实用性远比看上去的有限 一开始在大多数情况下(在这种情况下,我无法想象 唯一真正有用的保证是
throw()
,它 保证不会抛出任何异常;如果你想写 异常安全代码,您将需要对一些低级别 功能

实际上,虽然
throw()
可以允许一些额外的编译器 在优化过程中,通用实现往往会减少 使用异常规范时的高效代码。在C++11中
throw()
已被
noexcept
取代,大概是希望 编译器实现者将用它做一些智能的事情

编辑:

因为每个人(包括我自己)似乎都错过了你的问题4:

坏的\u alloc
将由
操作符new
函数抛出,如果它不能 分配内存

bad_cast
将由
dynamic_cast
抛出到 演员阵容失败的情况。(A
动态\u cast
到指针返回一个 在这种情况下为空指针。)

创建异常规范时,将引发
错误的\u异常
违反,前提是异常规范允许
坏异常
。 (换句话说,算了吧。)

如果您尝试将
typeid
与null一起使用,将抛出
bad\u typeid
指针

ios_base::failure
将在您请求流时抛出 错误案例

实际上:如果你想恢复,你会抓到
bad\u alloc
并在内存不足的情况下继续。也就是说不经常。 (从内存不足的情况中恢复非常非常困难。) 对于
bad\u cast
,可能更倾向于使用指针,并测试 空,如果您不确定。也没有理由去看电影
错误的类型ID
。大多数情况下,您可能需要测试IO错误 显式地,而不是将流配置为抛出异常;和 设置了
ios\u base::badbit
时的异常可能是异常(因为
表示硬故障的真正例外情况)。

问题1

不用麻烦了。它们是一个坏主意,在最新版本的语言中被弃用。它们对编译没有任何好处