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

iam*_*ind 94 c++ exception throw noexcept c++11

有没有之间的任何其他差别throw()noexcept除了被检查的运行时分别编译时间?

维基百科C++ 11文章表明不推荐使用C++ 03 throw说明符.
为什么这样,noexcept有足够的能力在编译时覆盖所有这些?

[注意:我提到了这个问题这篇文章,但没有得到弃用的充分理由.]

Nic*_*las 119

异常说明符已被弃用,因为异常说明符通常是一个糟糕的主意.noexcept之所以添加,是因为它是一个合理有用的异常说明符:知道函数何时不会抛出异常.因此它成为二元选择:将抛出的函数和不会抛出的函数.

noexcept添加而不是仅删除所有throw说明符,throw()因为noexcept更强大.noexcept可以有一个参数,编译时解析成一个布尔值.如果布尔值为真,那么noexcept棒.如果布尔值为false,则noexcept不会粘住,函数可能会抛出.

因此,您可以这样做:

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};
Run Code Online (Sandbox Code Playgroud)

是否CreateOtherClass抛出异常?它可能,如果T是默认构造函数可以.我们怎么说?像这样:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Run Code Online (Sandbox Code Playgroud)

因此,CreateOtherClass()抛出iff给定类型的默认构造函数抛出.这解决了异常说明符的一个主要问题:它们无法传播调用堆栈.

你不能这样做throw().

  • 是的,我知道。只是研究“noexcept”并阅读了一些关于它的问题/答案。我发现最重要的原因是,如果移动构造函数没有声明为“noexcept”,一些(可能是所有)STL 容器将不会使用它,但我没有意识到这一点。 (2认同)
  • @NicolBolas运行时调用`std :: terminate`。这是* WAY WORSE *!代码可以潜入具有标记为“ noexcept”的功能的发行版中,并且在运行时(在客户现场)会检测到违规。我的意思是编译器保证首先生成不会“抛出”异常的代码。 (2认同)
  • @NicolBolas:值得注意的另一个区别.如果函数被标记为`throws()`那么如果抛出异常,则堆栈**必须被展开到该函数的范围(因此函数中的所有自动变量都被销毁),此时`terminate()`被称为(通过`unexpected()`).如果函数被标记为"noexcept",那么如果抛出异常则调用terminate(堆栈的展开是实现定义的细节). (2认同)

CB *_*ley 32

noexcept 在编译时不会检查.

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

当声明noexceptthrow()尝试抛出异常的函数时,唯一的区别是一个调用terminate和其他调用unexpected以及后一种异常处理方式实际上已被弃用.