标记派生的实现noexcept的副作用是什么,而接口不是

时间:2018-10-22 21:56:31

标签: c++ inheritance polymorphism noexcept

我们有一个实现IUnknown(或我们不拥有的任何接口)的类。我们开始使用所有可能的优化方法标记了大多数方法,因为我们无论如何都不会抛出任何异常。尽管我们依赖的某些库可能会。提出了一个问题,是否应该将QueryInterface / AddRef / Release标记为noexcept,因为接口不是。

仅将某些派生类标记为noexcept时,是否有任何副作用或陷阱?

2 个答案:

答案 0 :(得分:4)

通常应谨慎使用noexcept。除非编译器能够证明该函数确实不会抛出任何异常,否则它必须插入一个动态处理程序以在发生异常时终止您的程序。因此,它不一定会导致您期望的优化。无论如何,将其添加到AddRefReleaseQueryInterface应该是安全的。

修改

例如,考虑以下代码:

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。

如果将其添加到某个位置并因该位置而崩溃,则说明您无法在此处使用它以及原因。