rlb*_*ond 27 c++ exception c++11
我很好奇背后的理由noexcept在的C++ 0x FCD.throw(X)被弃用了,但noexcept似乎做了同样的事情.有noexcept没有在编译时未检查的原因?看起来如果静态检查这些函数它们只会在一个try块中调用抛出函数会更好.
Vic*_*iba 25
如果我记得throw已被弃用,因为无法指定模板函数可以抛出的所有异常.即使对于非模板函数,您也需要throw子句,因为您添加了一些跟踪.
另一方面,编译器可以优化不抛出异常的代码.有关详细讨论,请参阅" 关于noexcept的争论,第一部分 "(以及第二部分和第三部分).主要观点似乎是:
过去二十年的丰富经验表明,在实践中,只有两种形式的例外规范是有用的:
缺少明显的异常规范,它指定一个可以抛出任何类型的异常的函数:
Run Code Online (Sandbox Code Playgroud)int func(); //might throw any exception一个永不抛出的功能.这样的函数可以用throw()规范表示:
Run Code Online (Sandbox Code Playgroud)int add(int, int) throw(); //should never throw any exception
spr*_*aff 25
基本上,它是一个链接器问题,标准委员会不愿意打破ABI.(如果由我决定,我会这样做,所有它真正需要的是库重新编译,我们已经有线程启用这种情况,并且它是可管理的.)
考虑一下如何解决问题.假设要求是
noexcept(true)
noexcept(true)
noexcept(false)除非另有说明,否则每个其他函数都是隐式的noexcept(true)函数必须包含所有的noexcept(false)调用try{}catch(...){}
听起来很合理吧?
要实现这一点,链接器需要区分函数noexcept(true)和noexcept(false)版本,就像您可以重载成员函数的const和const版本一样.
那么这对名字命名意味着什么呢?为了与现有的目标代码向后兼容,我们要求所有现有的名称都被解释为版本的noexcept(false)额外修改noexcept(true).
这意味着我们无法链接现有的析构函数,除非修改标题以将其标记为 noexcept(false)
我亲自与标准委员会成员谈过这个问题,他说这是一个匆忙的决定,主要是因为对集装箱搬运操作的限制(否则你可能会在投掷后丢失物品,这违反了基本保证) .请注意,这是一个男人,其陈述的设计理念是错误的不容忍代码是好的.得出自己的结论.
就像我说的那样,我会打破ABI而不是破坏语言.noexcept旧方式只是微不足道的改进.静态检查总是更好.
请注意,noexcept检查由失败引发的异常dynamic_cast并typeid应用于null指针,这只能在运行时完成.其他测试确实可以在编译时完成.
正如其他答案所述,诸如dynamic_casts之类的语句可能会抛出,但只能在运行时检查,因此编译器在编译时无法确定.
这意味着在编译时编译器可以让它们继续(即不进行编译时检查),警告或完全拒绝(这不会有用).这使得警告成为编译器唯一合理的事情.
但是这仍然没有用 - 假设你有一个dynamic_cast你知道永远不会失败的原因,因为你的程序是这样编写的,所以会抛出异常.编译器可能不知道这一点并抛出一个警告,它会变成噪声,可能只是被程序员禁用而无法使用,否定了警告的要点.
类似的问题是,如果你有一个未指定的函数noexcept(即可以抛出异常),你想要从许多函数中调用,有些函数,有些函数noexcept没有.你知道函数永远不会抛出函数调用的情况noexcept,但编译器也不会:更多无用的警告.
因此编译器在编译时强制执行此操作没有任何有用的方法.这更像是静态分析领域,对于这种事情往往更加挑剔和警告.
| 归档时间: |
|
| 查看次数: |
6318 次 |
| 最近记录: |