The standard throw()
doesn't enhance optimizability.
If a method is marked as throw()
then the compiler is forced to check if an exception is thrown from the method and unwind the stack - just like if the function is not marked as throw()
. The only real difference is that for a function marked throw()
the global unexpected_handler
will be called (which generally calls terminate()
) when the exception leaves the function, unwinding the stack to that level, instead of the behavior for functions without an exception specification which will handle the exception normally.
For pre-C++11 code, Sutter & Alexandrescu in "C++ Coding Standards" suggested:
Avoid exception specifications.
Take exception to these specifications: Don’t write exception
specifications on your functions unless you’re forced to (because
other code you can’t change has already introduced them; see
Exceptions).
...
A common but nevertheless incorrect belief is that exception
specifications statically guarantee that functions will throw only
listed exceptions (possibly none), and enable compiler optimizations
based on that knowledge
In fact, exception specifications actually do something slightly but
fundamentally different: They cause the compiler to inject additional
run-time overhead in the form of implicit try/catch blocks around the
function body to enforce via run-time checking that the function does
in fact emit only listed exceptions (possibly none), unless the
compiler can statically prove that the exception specification can
never be violated in which case it is free to optimize the checking
away. And exception specifications can both enable and prevent further
compiler optimizations (besides the inherent overhead already
described); for example, some compilers refuse to inline functions
that have exception specifications.
Note that in some versions of Microsoft's compilers (I'm not sure if this behavior has changed in more recent versions, but I don't think so), throw()
is treated in a non-standard way. throw()
is equivalent to __declspec(nothrow)
which does allow the compiler to assume that the function will not have an exception thrown and undefined behavior will result if one is.
C++11 deprecates the C++98 style exception specification and introduced the noexcept
keyword. Bjarne Stroustup's C++11 FAQ says this about it:
If a function declared noexcept throws (so that the exception tries to
escape, the noexcept function) the program is terminated (by a call to
terminate()). The call of terminate() cannot rely on objects being in
well-defined states (i.e. there is no guarantees that destructors have
been invoked, no guaranteed stack unwinding, and no possibility for
resuming the program as if no problem had been encountered). This is
deliberate and makes noexcept a simple, crude, and very efficient
mechanism (much more efficient than the old dynamic throw()
mechanism).
In C++11 if an exception is thrown from a function marked as noexcept
the compiler is not obligated to unwind the stack at all. This affords some optimization possibilities. Scott Meyers discusses the new noexcept
in his forthcoming book "Effective Modern C++".