5

在 C++11 中,这已被弃用:

void foo() throw();

并替换为

void foo() noexcept;

本文中解释了这样做的原因(其中归结为同一件事)是

C++ 异常规范是在运行时而不是在编译时检查的,因此它们不提供程序员保证所有异常都已被处理。

虽然这对我来说确实有意义,但我不明白为什么throw()首先动态检查,或者为什么noexcept不提供异常保证,而不是调用std::terminate而不是正常的堆栈展开(这并不是真正的可靠保证 IMO)。

难道不能在编译期间检查是否抛出异常,如果发生这种情况,编译会失败吗?在我看来,基本上有三种情况:

void foo() noexcept
{
    // 1. Trivial case
    throw myexcept();

    // 2. Try-catch case
    //    Necessary to check whether myexcept is derived
    //    from exception
    try 
    { 
        throw myexcept(); 
    } 
    catch(exception const & e)
    {}

    // 3. Nested function call
    //    Recursion necessary
    bar();
}

使用 C++ 中的模板为每种类型实例化,编译应用程序无论如何都需要永远 - 那么为什么不更改noexcept以强制编译器检查在编译期间是否抛出异常呢?

noexcept我看到的唯一困难是一个函数可能会或可能不会抛出取决于运行时状态 - 但在我看来,无论如何都不应该允许该函数调用自己。

我是否遗漏了一些东西,或者是为了不进一步增加编译时间,还是为了让编译器开发人员轻松一些?

4

1 回答 1

1

我认为这在很大程度上归结于这样一个事实,即在定义异常规范时,编译器编写者远远落后于功率曲线。实现 C++98 足够复杂,以至于只有一个编译器甚至声称实现了它的所有功能。每个其他编译器都至少遗漏了标准中包含的一个主要功能。大多数人相当公开地承认,他们遗漏的内容远不止这些。

您还需要记住,动态异常规范也远比throw(). 它允许程序员指定可以抛出的任意类型集。更糟糕的是,指定一个函数可以抛出foo意味着它也可以抛出任何派生的东西foo

静态地强制执行异常规范是可以做到的,但它显然会增加相当多的额外工作,而且没有人真正确定它会提供什么(如果有的话)好处。在这种情况下,我认为大多数人很容易认为,如果似乎有足够的用途来证明这项工作的合理性,那么以后可能需要静态强制执行。从运行时强制更改为编译时不需要修改现有代码,只需要修改现有实现。

另一点是,我不确定异常规范是否真的得到过强有力的支持。我认为在基本思想上达成了普遍共识,但当你深入了解它时,可能就不那么关心细节了。

底线:很容易只授权动态执行,而将静态执行留到以后(如果有的话)。事实证明,静态执法在任何情况下都可能不会真正增加那么多积极因素,因此强制它可能无论如何也不会取得太大成就。

于 2013-08-13T07:34:09.467 回答