[[Josuttis]] P25 is concise on this topic, and explains why noexcept is superior.
Background – all exception specs beside these 2 are deprecated in c++11. Only these 2 forms proved useful. Let’s rephrase the question as “Real difference between 2 otherwise identical functions, one with empty throw() the other without throw”.
Short Answer — wrapping the empty-throw function call in try/catch is useless.
Short answer – empty throw means “should throw Nothing. Nothing expected“;
Short answer – missing throw means the opposite — “all exceptions expected”
Long answer — suppose you wrap each function call in a try/catch (…) ie catch-all. For the function without throw, every single exception from it will fall into your catch(…). For the empty-throw function, every single exception always, always triggers unexpected(). Your try/catch is ignored by compiler — could be removed during compilation.
Now we are ready to look at a function with throw(A). According the ARM, if at runtime this function throws unlisted exceptions, it’s seen as a serious design fault, so serious that compiler will *disregard* your try/catch — paper over (huge) cracks.
Here’s a best practice from http://www.gotw.ca/publications/mill22.htm — Moral #1: Never write an exception specification. If you follow this advice, then your try/catch will work, ie won’t be stripped off by compiler
My advice — “Either don’t list the exceptions, or adhere to your list. If you bother to list the expected exceptions, then stick to it. Don’t throw anything else. ”
Note unexpected() is called always, always due to an explicit exception-spec i.e. an explicit throw suffix. “Unexpected” means “function author informed compiler to *expect* some exceptions, but something unexpected came out from the function“.
Let’s repeat the message — whenever you notice unexpected() invoked, there’s a function with a broken exception spec — No smoke without fire. No throw suffix then no “unexpected()”.
Further, these 2 conditions always lead to each other —
function has an exception list, but unlisted exceptions generated unexpected() invocation
What about terminate()? It’s somewhat peripheral in the story of exception-spec. I will just describe one of the causes — an expected (i.e. listed) exception is thrown but not caught. Also, unexpected() calls terminate() by default.