我们有一个实现IUnknown(或我们不拥有的任何接口)的类。我们开始使用所有可能的优化方法标记了大多数方法,因为我们无论如何都不会抛出任何异常。尽管我们依赖的某些库可能会。提出了一个问题,是否应该将QueryInterface / AddRef / Release标记为noexcept,因为接口不是。
仅将某些派生类标记为noexcept时,是否有任何副作用或陷阱?
答案 0 :(得分:4)
通常应谨慎使用noexcept
。除非编译器能够证明该函数确实不会抛出任何异常,否则它必须插入一个动态处理程序以在发生异常时终止您的程序。因此,它不一定会导致您期望的优化。无论如何,将其添加到AddRef
,Release
和QueryInterface
应该是安全的。
修改
例如,考虑以下代码:
extern int Foo();
int Bar() noexcept
{
return Foo();
}
这是Clang 7.0在O3上生成的:
Bar(): # @Bar()
push rax
call Foo()
pop rcx
ret
mov rdi, rax
call __clang_call_terminate
__clang_call_terminate: # @__clang_call_terminate
push rax
call __cxa_begin_catch
call std::terminate()
如果删除noexcept
,则会得到以下信息:
Bar(): # @Bar()
jmp Foo() # TAILCALL
在此示例中,主要效果只是使图像有些膨胀,但请注意,对Foo
的调用也变得效率较低。
答案 1 :(得分:0)
我总是建议尽可能添加noexcept。
如果将其添加到某个位置并因该位置而崩溃,则说明您无法在此处使用它以及原因。