-
Notifications
You must be signed in to change notification settings - Fork 82
Exceptions
- Always guarantee at least the basic exception guarantee (2)!
- If you can, enforce the strong exception guarantee (3)
- move construction, move assignment and swap should always be no-throw
See section Exception-Safety for details on exception safety.
When do we use noexcept
:
- If we can ensure that everything within the function body can never throw
- If it is critical that the function does not throw (move semantics)
- Try to always make move construction, move assignment and swap
noexcept
! - Use the
noexcept()
-operator if necessary
- Try to always make move construction, move assignment and swap
- If there is a measurable performance gain (tests!)
Note: Since explicitly defaulted constructors are noexcept
if they can, do not explicitly declare them noexcept
, except if you want to enforce this.
See section The noexcept specifier (C++11) for details on noexcept
.
Related issue: #45 Related design discussion: 2020-03-30
Safety-Guarantee
- none or unknown
- basic (invariants of the component are preserved, and no resources are leaked)
- strong (if an exception is thrown there are no effects)
- no-throw (the code will never ever throw)
Adding noexcept
to you function declaration will tell the compiler: This function never throws!
void my_function() noexcept // "will never throw"
{
// ...
}
-
Ensures the no-throw exception guarantee (see above)
-> can be used accordingly (e.g. when using it in another function to ensure a strong exception guarantee)
-
The compiler may optimize your code (e.g. efficient move with std::move_if_noexcept)
What happens if you throw from a noexcept
function? Your program terminates, usually without unwinding the stack.
- Terminating the program isn't the nicest way to report an error to your user.
- Terminating prevents any error handling
- Removing
noexcept
can break the API
Take home message: Use noexcept
if you are sure, avoid if in doubt.
If you are not sure if something throws, you can use a conditional noexcept
:
template <typename t>
int my_function(t & v) noexcept(noexcept(std::declval<t &>().size()))
{
return v.size();
}
- Functions that are declared
noexcept
- Construction of trivial types (e.g.
int
) - Explicitly defaulted constructor and assignment operator
foo() = defaulted;
(c++11) are implicitely noexcept and constexpr if they can (see stack overflow which references the standard)
- https://blog.quasardb.net/when-noexcept-2/
- https://visualstudiomagazine.com/articles/2016/10/01/noexcept.aspx
- https://www.modernescpp.com/index.php/c-core-guidelines-the-noexcept-specifier-and-operator
- https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
- https://isocpp.org/blog/2014/09/noexcept-optimization