Question

I found that there are three ways to catch an exception, what are the differences?

1) catch by value;

2) catch by reference;

3) catch by pointer;

I only know that catch by value will invoke two copies of the object, catch by reference will invoke one. So how about catch by pointer? When to use catch by pointer? In addition to throw an object, can I throw a pointer to an object like this?

class A {}

void f() {

  A *p = new A();
        throw p;


}
Was it helpful?

Solution

The recommended way is to throw by value and catch by reference.

Your example code throws a pointer, which is a bad idea since you would have to manage memory at the catch site.

If you really feel you should throw a pointer, use a smart pointer such as shared_ptr.

Anyway, Herb Sutter and Alexei Alexandrescu explain that really well in their C++ Coding Standards book which I paraphrased.

See C++ Coding Standards: Throw by Value, Catch by Reference.

OTHER TIPS

Catch follows normal assignment compatibility rules, that is, if you throw a value, you can catch it as value or reference, but not as pointer; if you throw a pointer, you can catch it only as a pointer (or reference to a pointer...).

But it doesn't really make sense to throw pointers, it will only cause memory management headaches. Thus, you should, in general follow the rule throw by value, catch by reference, as explained by Gregory.

Microsoft's MFC uses catch by pointer, but I think that was for compatibility with the compiler before try and catch were properly implemented; originally they used TRY and CATCH macros to simulate it. Each exception derives from CException, which has a method to determine whether the object needs to be deleted.

I wouldn't recommend that for any modern exception design. Catch by reference is the way to go.

While it's possible to throw essentially any object of any type, there's little (if anything) to be gained by doing this. Dynamic allocation is useful primarily when an object needs to have a lifetime doesn't fit with automatic allocation -- i.e. you want its lifetime to be independent of normal program scope.

In the case of an exception object, however, that doesn't really make much sense. An exception object is normally only used inside of an exception handler, and you clearly want it to be destroyed when you exit the (last) handler for that exception.

There's also the fact that you generally want to keep exception handling code fairly simple. Just for example, if you're trying to report the free store/heap being exhausted or corrupt, trying to allocate your exception object off that exhausted/corrupt free store/heap usually won't work very well...

There isn't really a good scenario for catching/throwing an exception by pointer. C++ semantics allow it, but it's not terribly useful, as most of the time you'll be throwing a temporary exception or string object.

However, some libraries (Boost.Graph does this, I believe) use throw to pass a return value back to the caller from a deeply recursed function; in a situation like this, the return value may be a pointer, so throwing a pointer would make sense.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top