C ++ 03 throw()说明符C ++ 11 noexcept之间的区别


100

有什么区别throw()noexcept其他比分别运行时和编译时,被检查?

这篇Wikipedia C ++ 11文章建议不要使用C ++ 03 throw指定符。
为什么这样,有noexcept能力在编译时覆盖所有内容?

[注意:我检查了这个问题本文,但无法确定不赞成使用的理由。]


7
擅长这篇文章noexcept可能会导致运行时检查。它们之间的主要区别是断裂noexcept引起std::terminate而断裂throw引起std::unexpected。在这些情况下,堆栈的展开行为也略有不同。
Fiktik

没有对带有某些异常规范的“编译时间”进行检查,而对其他异常规范进行了“运行时”检查。这只是C ++异常规范的反对者所创造的神话。
curiousguy

Answers:


129

不赞成使用异常说明符,因为异常说明符通常是一个糟糕的主意noexcept之所以添加它,是因为它是异常说明符的一种合理有用的用法:知道何时函数不会引发异常。因此,它成为二元选择:将要抛出的函数和将不会抛出的函数。

noexcept被添加,而不是仅仅删除所有的抛出说明符,throw()因为noexcept它更强大。noexcept可以具有一个在编译时解析为布尔值的参数。如果布尔值为true,则noexcept坚持。如果布尔值为false,则noexcept不会坚持,并且该函数可能会抛出。

因此,您可以执行以下操作:

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};

是否CreateOtherClass抛出异常?如果T默认的构造函数可以的话,它可能会。我们怎么知道?像这样:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};

因此,CreateOtherClass()将在给定类型的默认构造函数引发时抛出。这解决了异常说明符的主要问题之一:它们无法沿调用堆栈向上传播。

您无法使用来做到这一点throw()


+1有用的答案,无论如何对我来说。仍在寻找一个答案,说明我为什么要使用noexcept。我从没使用过throw()说明符,并且一直在尝试确定是否noexcept确实提供了任何好处(除了编译器检查的文档之外)。
hmjd 2013年


1
@NicolBolas同意。但是如果没有保证,编译器可以检查函数是否可以在析构函数中抛出。这样就可以警告程序员一个函数是否异常。
亚历克斯

2
@NicolBolas运行时调用std::terminate。这是值得担心的!代码可以潜入带有标记功能的发行版中,noexcept 并在运行时(在客户现场)检测到违规情况。我的意思是编译器保证首先生成不会引发异常的代码。
亚历克斯

2
@NicolBolas:另一个值得注意的区别。如果标记了一个函数,throws()则如果引发了异常,则必须terminate()调用该点(通过unexpected())之前将堆栈展开至该函数的范围(这样,该函数中的所有自动变量都将被销毁)。如果标记了函数,noexcept则如果引发了异常,则调用终止(堆栈的展开是实现定义的细节)。
马丁·约克

33

noexcept 在编译时不检查。

一个实现不应仅仅因为在执行时抛出或可能抛出包含函数不允许的异常而拒绝表达式。

当一个函数被声明noexceptthrow()试图抛出异常时,唯一的区别是一个调用terminate和其他调用unexpected以及后一种异常处理样式已被有效弃用。


但是,如果虚函数具有throw()/ noexcept,则编译时检查请确保覆盖程序也具有。
curiousguy19年

2

std::unexpected() 当违反动态异常规范时,由C ++运行时调用:从一个函数抛出异常,该函数的异常规范禁止这种类型的异常。

std::unexpected() 也可以直接从程序中调用。

无论哪种情况,都std::unexpected调用当前安装的std::unexpected_handler。默认std::unexpected_handler调用std::terminate

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.