Exception handling is a crucial part of any large scale software development where independently developed part of a program communicate. C++ like many other main stream programming language provide try and catch constructs to handle exceptions. On a high level, handling exception involves the following steps

You wrap the code prone to exception inside a try{..} block. This try{..} block is followed by a series of catch(){..} blocks i.e. handlers where you handle the exception fully or partially. If an exception is raised stack unwinding begins until a matching catch(){..} block is found and upon then program execution resumes within the matched handler. If the exception is partially handled, it may be thrown again and lead to program termination if no matching catch(){..} block is found. Otherwise, the execution resumes after the try{..} block.

Now let’s talk about constructors a bit. In a large code-base a class can compose objects of other classes or inherit from them or both. Something like this

Every time the object of class A is created, its constructor must call some constructor of class B and class C. If not done, compiler inserts calls to default constructors of B and C. But what if we’ve to call non-default constructors of B and C or initialize a reference member of A? Most efficient way is to use initialization list as below

While the initialization list is being executed there is a chance of exception i.e before program control enters inside constructor body . If so, what happens to the object which is being created? Will destructor be called? Will the partial object be returned to the calling method? Let’s dive in.

To handle exceptions arising in from the initialization list C++ provides function try block. They can also be used with regular functions and destructors; but those cases are rare and carry a few peculiarities .

This is what a function try block looks like

Function try block is like a normal try{..} block, but it doesn’t go inside the function’s body. Instead, it wraps the function definition, and the initialization list in case of constructors, associating a series of catch(){} clauses with entire function body. Even though, function try block can be used with regular functions and destructors as well, it makes more sense to use them with constructors having initialization list. Why? We’ll see later in the post.

There a few restrictions with function try block.

When used with constructors, you can’t jump in or jump out of the handler of the function try block. The only way out of handler is re-throwing the same or another exception. If control reaches the end of the handler same exception is automatically thrown.

2. Since there is no way to know how farther in the initialization list the exception occurred, any member or base class sub-objets created so far are destroyed before entering inside the handler. Moreover, the non-static members or base class can’t be accessed, thus you can’t attempt any sort of recovery. This is the intentional behavior.

So when to use function try block?Or rather not use.

Since it’s recommended for destructor to not throw any exception; reaching the end of the catch handler of function try block on a destructor rethrows the same exception, albeit return statement is allowed. Throwing exception from destructor can cause leak in your program. It is because in case of inheritance, where the order of destructor calls is from most derived class towards the base class, any exception thrown during these calls will leave the object partially destroyed. Reaching the end of a regular function is as good as return; if the function return type is void ; otherwise the behavior is undefined. Moreover, using them with void functions and constructors without initialization list doesn’t accomplishes anything. Better to use normal try{..} catch(){..} block inside the body instead.

Don’t use function try block to catch exception thrown from inside the constructor or function body. If you land in the catch handler of a function try block because of an exception(a bad_alloc for example) inside constructor or function body, it’s advised to handle them using normal try{..}catch(){..} block inside function body. For memory allocation use of RAII is recommended; but if you’ve to allocate memory through different ways do it inside the constructor body; never in initialization list. Also, in case when you want to go ahead with the construction of object even though construction of some of it’s parts fails, use pointers to the class sub-object instead of sub-objects as members. This way those null pointers will reflect the failure of construction of sub objects.

In summary, the only scenario where you should use function try block is when your constructor’s initialization list has at least one call to a user-defined constructor which can throw. Since such exception can’t be absorbed, function try block isn’t meant to recover from the failure and attempt reconstruct the object. At the maximum, you can replaced the exception being thrown and cause some useful side effects such as log the failure. Additionally, use of function try block with regular functions and destructor is rare.