what does "throw;" outside a catch block do?
I just stumbled this code:
voi开发者_StackOverflow社区d somefunction()
{
throw;
}
and I wonder: what does it mean?
The intent is probably that somefunction()
is only ever called from inside some catch
block. In that case, there would be an exception active when the throw;
is executed, in which case the current exception is re-thrown, to be caught by the next outer handler that can handle that exception type.
If throw;
is executed when an exception is not active, it calls terminate()
(N4810, §[expr.throw]/4).
It re-throws the currently active exception. It would only make sense to call it (possibly indirectly) from a catch-block. This:
#include <iostream>
using namespace std;
void f() {
throw;
}
int main() {
try {
try {
throw "foo";
}
catch( ... ) {
f();
}
}
catch( const char * s ) {
cout << s << endl;
}
}
prints "foo".
For throw
the concept of being "outside" or "inside" catch block is defined in run-time terms, not in compile-time terms as you seem to assume. So, if during run-time that throw
is executed in run-time context of a catch
block, then throw
works as expected. Otherwise, terminate()
is called.
In fact, if you take a closer look at how C++ exceptions are defined in the language specification, a lot of things about them are defined in run-time terms. Sometimes it even appears to be un-C++-like.
People have already explained what it means but it's potentially useful to know why you might see it. It's a useful way to construct a 'generic' exception handler that deals with exceptions based on their type so as to reduce the amount of duplicated code.
So, if we take Neil's example and expand on what f()
might be doing we might end up with an implementation which does something like my LogKnownException()
function that I proposed in this answer.
If you are working in an team that likes to log all manner of exceptions all over the place then rather than having a huge collection of catch blocks at all of these places (or even worse a macro) you can have a simple catch block that looks like this
catch(...)
{
LogKnownException();
}
Though I expect I'd change my previous example of LogKnownException()
to one that simply allowed exceptions that it didn't want to log to propagate out and continue on in an unhandled fashion.
I'm not suggesting that this is necessarily a good thing to do, just pointing out that this is where you're likely to see the construct used.
精彩评论