为什么用新语法`noexcept`重写旧的空抛出规范?

问题描述 投票:1回答:1

标题说明了一切:为什么C ++放弃了完美令人满意的,有用的空抛出规范throw(),以另一种语法替换它,并引入了新关键字noexcept

空抛出规范是“仅抛出这些枚举异常保证”(写为throw(X,Y,Z)),但枚举异常为零:您不抛出XYZ(以及派生类型),而是可以抛出空集:这是函数从不向调用者抛出任何东西的保证,换句话说,从不抛出或“不抛出”规范

那是使用基本上相同的工具免费地制作了新代码,表达了相同的承诺,与旧代码不兼容,并且不赞成使用旧代码,然后又禁止了旧代码,无缘无故破坏了向后兼容性?

是什么引起了throw()的这种仇恨?

据我所知,只有旧的不安全gets和愚蠢的无用的隐式int被严厉对待。

编辑:

[所谓的“重复”是基于虚假陈述。

在所谓的“动态异常规范”中没有“动态”。这是我最讨厌的新的throw规范:与“动态”和“静态”相对的无用术语的含义。

c++ exception compatibility language-design noexcept
1个回答
2
投票

[使用基本相同的工具免费地制作了新代码,表达了相同的承诺,与旧代码不兼容

更正:如果函数违反了动态异常规范,则会调用std::unexpected,它会调用意外的处理程序,默认情况下会调用std::terminate。但是处理程序可以由用户功能代替。如果某个函数违反了noexcept,则直接调用std::terminate

承诺是不同的。 throw()的意思是“如果尝试发出异常,可能会发生意外的事情”。 noexcept表示“如果尝试发出异常,将立即终止。”

[仅在C ++ 17中,throw()完全等于noexcept。这是在6年的异常规范(包括throw())被弃用之后。

应注意,unexpected差异在first papers about noexcept中明确引用。具体来说:

请注意,noexcept作为优化提示的用途远远超出了N2855引入的狭义情形。实际上,它超出了移动构造的范围:当编译器可以确定地检测到非抛出操作时,它可以优化掉大量专门用于异常处理的代码和/或数据。一些编译器已经针对noexcept(true)规范进行了此操作,但是由于这些编译器会产生隐式try / catch块来处理意外异常的开销,因此其好处是有限的。

隐式try / catch块是必需的,因为在将堆栈展开到throw()函数之后必须调用unexpected。在throw()的第一个版本中,发出异常的是纯正UB,而后来的版本则切换为noexcept。但是即使那样,也无法保证放松。

什么引起了throw()的这种仇恨?

更正:不重新使用结构并不表示恶意。尤其是在发明新的结构时,可以避免兼容性破坏,如上所示。

注意,就std::terminate表达式而言,throw()被认为等同于noexcept功能。也就是说,调用noexcept函数不会引发异常,并且throw()表达式将导致noexcept(empty_throw())

还应注意,无论如何都需要一个新的关键字。为什么?因为C ++ 98/03中的true已具有含义。 throw(<stuff>)对于noexcept(<stuff>)具有非常不同的含义。从解析的角度来看,试图将<stuff>内容放到noexcept说明符中会很困难。

此外,您现在可以将此新关键字用作通用表达式:如果throw中的所有调用均未引发异常,则解析为noexcept(<expression>)。这使您可以根据事物是否会引发异常来执行条件逻辑。您需要一个新的关键字来执行类似的操作(否则,您将不得不使用难看的语法,而C ++的处理方式太多了。)

© www.soinside.com 2019 - 2024. All rights reserved.