"Function can be declared 'noexcept'."

C++ Core Guidelines F.6: If your function may not throw, declare it noexcept

If code is not supposed to cause any exceptions, it should be marked as such by using the 'noexcept' specifier. This would help to simplify error handling on the client code side, as well as enable compiler to do additional optimizations.


  • A function is considered non-throwing if:
    • it has no explicit throw statements;
    • function calls in its body, if any, invoke only functions that unlikely to throw: constexpr or functions marked with any exception specification which entails non-throwing behavior (this includes some non-standard specifications).
  • Non-standard and outdated specifiers like throw() or declspec(nothrow) are not equivalent to 'noexcept'.
  • Explicit specifiers noexcept(false) and noexcept(true) are respected appropriately.
  • Functions marked as constexpr are not supposed to cause exceptions and are not analyzed.
  • The rule also applies to lambda expressions.
  • The logic doesn't consider recursive calls as potentially non-throwing. This may change in the future.


All functions except the destructor will warn because they are missing noexcept.

struct S
    S() {} // C26455, Default constructor may not throw. Declare it 'noexcept'
    ~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() noexcept {}
    ~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*/}