Summary of noexcept usage #651
ivankochin
started this conversation in
Design discussions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Potential benefits of noexcept, or why one would want to use it
Performance optimization
Compiler has to generate exception handling code for stack unwinding to correctly handle possible exceptions. Marking functions as noexcept developers can help the compiler to generate more efficient code telling "The function can't throw an exception. Just trust me, compiler".
Size of binary (cross-translation-unit optimization)
As previously said, a compiler can optimize calls of non-throwing functions. So how a compiler can understand that function
foo()
from another object file is not going to throw an exception? Adding noexcept to the declaration offoo()
helps the compiler to check for non-throwing guarantee in compile time. And ifnoexcept(noexcept(foo()))
evaluates into true compiler won't generate exception handling code reducing the size of binary - which is important (e.g. for embedded platforms).Algorithmic optimizations based on stated guarantees
Some STL containers intend to give a strong exception guarantee (it means "If the function throws an exception, the state of the program is rolled back to the state just before the function call. For example,
std::vector::push_back
" (c) cppreference).So in some of their methods, containers use std::move_if_noexcept and std::is_nothrow_move_constructible constructions to check whether the move constructor potentially invalidates container state or not. Even if your class has a move constructor but it's not marked as noexcept - the container will call a more preferable choice to guarantee that invalidating of invariant is impossible.
Declaring/documenting intended behavior
Using noexcept could add clarity to the code declaring the programmer's intent that a function or method should not throw (in a similar way as const specifier indicates that function doesn't modify the state).
NOTE: Unless noexcept is nested with sophisticated constructions such as
noexcept(noexcept(foo()) && noexcept(bar()) && noexcept(SomeType::size()))
Guarantee of program termination on exception
it's guaranteed by the standard that std::terminate will be called if an exception emits from the noexcept-marked function (stack-unwinding can be performed probably at most). E.g. it's used in Parallel STL because the standard requires to call
std::terminate
if the function passed to the algorithm throws an exception. Deallocation functions and destructors are noexcept by default since C++11.Do these benefits apply to TBB?
Performance optimization
Modern compilers are smart enough to understand whether functions throw an exception or not in the vast majority of cases. So they optimize by themselves at least inlined functions without additional information from the developer of that function. Moreover, modern exception handling techniques have zero overhead until an exception is really thrown.
Size of binary (cross-translation-unit optimization)
TBB is the primary header-implemented library so the potential field of cross-translation-unit optimization and reducing of binary size is lacking.
Algorithmic optimizations based on stated guarantees
This is the most valuable benefit. Definitely for movable objects. So e.g. for
tbb::blocked_range
, it's not relevant because copy and move constructors are the same and will not gain any performance.Declaring/documenting intended behavior
As it was mentioned in the previous part, it might be useful unless it's overly complicated.
The majority of functions are exception-neutral. Such functions call other functions/constructors, and in order to properly determine whether the function may throw or not, it's necessary to write complicated conditions and reduce the readability.
Moreover, noexcept might impact backward compatibility: adding it is easy enough but removing breaks the ABI (as users can depend on a non-throwing guarantee). So you have to be sure that the function will never be changed to throw.
Guarantee of program termination
We don't provide such functionality and no one requires from us such a guarantee (even Parallel STL because they don't depend on functions that are passed to algorithms).
Summary
Probably a lot of discussions about noexcept happen because developers don't easily recognize when this specifier really adds value for their code.
For us:
Sources
Beta Was this translation helpful? Give feedback.
All reactions