I'd like to ask this question (also here), but this time about C++.
What is the difference in C++ between
try { /*some code here*/开发者_运维问答}
catch(MyException& ex)
{ throw ex;} //not just throw
and
try { /*some code here*/}
catch(MyException& ex)
{ throw;} //not throw ex
Is it just in the stack trace (which in C++ is in any case not a standard as in C# or Java)?
(If it makes any difference, I use MSVS 2008.)
throw;
rethrows the same exception object it caught while throw ex;
throws a new exception. It does not make a difference other than the performance reasons of creating a new exception object. If you have a exception hierarchy where there some other exception classes derived from MyException
class and while throwing an exception you have done a throw DerivedClassException;
it can be caught by the catch(MyException&)
. Now if you modify this caught exception object and rethrow it using throw;
the type of exception object will still be DerivedClassException
. If you do throw Ex;
the object slicing occurs and the newly thrown exception will be of type MyException
.
[C++ FAQ Lite § 17.9] What does
throw;
(without an exception object after thethrow
keyword) mean? Where would I use it?You might see code that looks something like this:
class MyException { public: ... void addInfo(const std::string& info); ... }; void f() { try { ... } catch (MyException& e) { e.addInfo("f() failed"); throw; } }
In this example, the statement
throw;
means "re-throw the current exception." Here, a function caught an exception (by non-const reference), modified the exception (by adding information to it), and then re-threw the exception. This idiom can be used to implement a simple form of stack-trace, by adding appropriate catch clauses in the important functions of your program.Another re-throwing idiom is the "exception dispatcher":
void handleException() { try { throw; } catch (MyException& e) { ...code to handle MyException... } catch (YourException& e) { ...code to handle YourException... } } void f() { try { ...something that might throw... } catch (...) { handleException(); } }
This idiom allows a single function (
handleException()
) to be re-used to handle exceptions in a number of other functions.[C++ FAQ Lite § 17.11] When I throw this object, how many times will it be copied?
Depends. Might be "zero."
Objects that are thrown must have a publicly accessible copy-constructor. The compiler is allowed to generate code that copies the thrown object any number of times, including zero. However even if the compiler never actually copies the thrown object, it must make sure the exception class's copy constructor exists and is accessible.
(edited for more clarity on what I thought was obvious...)
catch(MyException& ex) { throw ex; }
may copy ex
, with all the issues that it entails; catch(MyException& ex) { throw; }
may not.
If you have an exception hierarchy, throw ex
can slice your exception, while throw
won't. For example:
#include <iostream>
#include <string>
using namespace std;
struct base
{
virtual string who() {return "base";}
};
struct derived : public base
{
string who() {return "derived";}
};
int main() {
try {
try {
throw derived(); // throws a 'derived'
}
catch (base& ex)
{
throw ex; // slices 'derived' object to be a 'base' object
}
}
catch (base& ex)
{
cout<<ex.who()<<endl; // prints 'base'
}
}
Change throw ex
to just throw
, and you'll get an output of derived
, which is what you probably expected to get.
You can use the throw;
form with catch(...)
(that is it is the only way to rethrow if you caught using catch(...) ).
There's a big difference. I wrote about it on my blog, at: https://cpptalk.wordpress.com/2009/08/23/nuances-of-exception-rethrow/
You are more than welcome to have a look
throw ex
will make another copy and is not recommend use throw
only to throw the current exception object.
throw can throw a nonstandard exception type that was caught by catch(...) (eg structured exception)
Additionally, since it sometimes causes confusion, a bare throw;
outside of an exception-handling context will abort the program.
精彩评论