We have a class which implements IUnknown (or any interface which we don't own). We started marking most/all of our methods with noexcept for any potential optimization since we don't throw any exceptions anyway; although some of the libraries we depend on may. The question was raised whether or not QueryInterface/AddRef/Release should be marked noexcept since the interface isn't.
Are there any side effects or gotchas when only some of the derived classes are marked noexcept?
You should be careful with noexcept
in general. Unless the compiler can prove that the function really won't throw any exceptions, then it must insert a dynamic handler to terminate your program in case of an exception. Thus it won't necessarily lead to the optimizations you're hoping for. In any case, adding it to AddRef
, Release
, and QueryInterface
should be safe.
Edit
For example, consider the following code:
extern int Foo();
int Bar() noexcept
{
return Foo();
}
This is what Clang 7.0 generates on 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()
If you delete the noexcept
, you get this instead:
Bar(): # @Bar()
jmp Foo() # TAILCALL
In this example, the primary effect is just to bloat the image a little bit, but notice that the call to Foo
also became a little less efficient.