Avoiding copies in exception handling
Can I avoid the cop开发者_如何学运维ying of object in the following way?
MyClass Obj;
try {
throw &Obj;
}
catch(MyClass *a) {
}
If the object is too expensive to copy, it should not be thrown as an exception - full stop. Exception classes should be fairly simple and light-weight. And you should always catch exceptions by reference (probably by const reference) - catching pointers is bad style. So your code should better be written:
try {
throw MyClass();
}
catch( const MyClass & a) {
}
In response to your comment, this:
struct A {
A() {}
private:
A( const A & ) {}
};
int main() {
throw A();
}
should be an error. But you simply should not be prohibiting copying of classes you want to throw as exceptions - why are you doing this?
Don't do it.
Consider this program:
#include <iostream>
#define X() (std::cout << __FUNCTION__ << "\n")
struct MyClass {
MyClass() { X(); }
~MyClass() { X(); }
};
void f() {
MyClass Obj;
throw &Obj;
}
int main() {
try {
f();
} catch(MyClass *a) {
X();
}
}
the output of which is this:
MyClass
~MyClass
main
Notice that the pointed-to object is destroyed before the program entered the catch block. This means that we must not dereference a
in the catch block, severely limiting its usefulness.
It is syntactically correct and avoids the copy since the reference is being passed. But, usually an standard nameless exception object is constructed and is caught by the catch
statement.
The only way to avoid copying an exception object is to throw a pointer to the object, as you have done in your example. You must make sure that the object is static or heap allocated, not a local object that will disappear after leaving the code block during the throw.
Edit: Another approach comes to mind. You can create your own exception class (which should be derived from std::exception
or one of its children) with the pointer as a member, then throw that. If you use a smart pointer such as shared_ptr
you won't have to worry about the lifetime of the contained object.
精彩评论