Warning C26439
This kind of function may not throw. Declare it 'noexcept'.
C++ Core Guidelines F.6: If your function must not throw, declare it noexcept
Some operations should never throw exceptions. Their implementations should be reliable and should handle possible errors conditions gracefully. They shouldn't use exceptions to indicate failure. This rule flags cases where such operations aren't explicitly marked as noexcept
, which means that they may throw exceptions and consumers can't make assumptions about its reliability.
It's important for these functions to be reliable as they're often used as building blocks to implement functions with exception safety guarantees. A move constructor that throws will force Standard Template Library (STL) containers to fall back to copy operations, reducing runtime performance.
Code analysis name: SPECIAL_NOEXCEPT
Remarks
Special kinds of operations:
- destructors;
- move constructors and move assignment operators;
- standard functions with move semantics:
std::move
andstd::swap
.
Nonstandard and outdated specifiers like
throw()
ordeclspec(nothrow)
aren't equivalent tonoexcept
.Explicit specifiers
noexcept(false)
andnoexcept(true)
are respected appropriately.
Example
The tool warns on all functions except the destructor because they're missing noexcept
.
struct S
{
~S() {}
S(S&& s) {/*impl*/} // C26439, This kind of function may not throw. Declare it 'noexcept' (f.6)
S& operator=(S&& s) {/*impl*/} // C26439, This kind of function may not throw. Declare it 'noexcept' (f.6)
S(const S& s) {/*impl*/} // C26440, This function can be declared 'noexcept'
S& operator=(const S& s) {/*impl*/} // C26440, This function can be declared 'noexcept'
};
With noexcept
decorating the same structure, all warnings are removed.
struct S
{
~S() {}
S(S&& s) noexcept {/*impl*/}
S& operator=(S&& s) noexcept {/*impl*/}
S(const S& s) noexcept {/*impl*/}
S& operator=(const S& s) noexcept {/*impl*/}
};