Almost all functions are assumed to be potentially throwing unless you explicitly use a noexcept specifier. The exceptions are for your own definitions of delete (deallocation functions), and some special member functions: constructors, destructors, and assignment operators. (C++17)
From [except.spec]
If a declaration of a function does not have a noexcept-specifier, the declaration has a potentially throwing exception specification unless it is a destructor or a deallocation function or is defaulted on its first declaration, in which cases the exception specification is as specified below and no other declaration for that function shall have a noexcept-specifier.
Constructors
Are implicitly noexcept unless any initialization performed for any member (or a member's member etc) is potentially throwing
Destructors
Are implicitly noexcept unless any destructor for a potentially constructed sub-object is potentially throwing.
Assignment operators
Are implicitly noexcept unless any use of assignment within is potentially-throwing.
Here's some sample code that demonstrates the above (clang 6.0.0, gcc 8.0.0):
int foo() { return 1; } int bar() noexcept{ return 1; } struct Foo{}; struct Bar{ Bar(){} }; int main() { static_assert(noexcept(bar())); static_assert(!noexcept(foo())); static_assert(noexcept(Foo())); static_assert(noexcept(Foo().~Foo())); static_assert(noexcept(Foo().operator=(Foo()))); static_assert(!noexcept(Bar())); Bar b; static_assert(noexcept(b.~Bar())); }
Yet another reason to use =default or allow the compiler to generate its own versions of your special member functions via omission.
noexceptof a function.