Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finally in C++

Is this a good way to implement a Finally-like behavior in standard C++? (Without special pointers)

class Exception : public Exception
    { public: virtual bool isException() { return true; } };

class NoException : public Exception
    { public: bool isException() { return false; } };


Object *myObject = 0;

try
{
  // OBJECT CREATION AND PROCESSING
  try
  {
    myObject = new Object();

    // Do something with myObject.
  }

  // EXCEPTION HANDLING
  catch (Exception &e)
  {
    // When there is an excepion, handle or throw,
    // else NoException will be thrown.
  }

  throw NoException();
}

// CLEAN UP
catch (Exception &e)
{
  delete myObject;

  if (e.isException()) throw e;
}
  1. No exception thrown by object -> NoException -> Object cleaned up
  2. Exception thrown by object -> Handled -> NoException -> Object cleaned up
  3. Exception thrown by object -> Thrown -> Exception -> Object cleaned up -> Thrown
like image 585
Tamara Wijsman Avatar asked Dec 24 '08 01:12

Tamara Wijsman


People also ask

What is finally block in C?

By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement.

What does the Finally statement do?

What Is finally? finally defines a block of code we use along with the try keyword. It defines code that's always run after the try and any catch block, before the method is completed. The finally block executes regardless of whether an exception is thrown or caught.

Do we have finally in C++?

No, C++ does not support 'finally' blocks. The reason is that C++ instead supports RAII: "Resource Acquisition Is Initialization" -- a poor name† for a really useful concept.

Is finally always executed C#?

A finally block always executes, regardless of whether an exception is thrown.


2 Answers

The standard answer is to use some variant of resource-allocation-is-initialization abbreviated RAII. Basically you construct a variable that has the same scope as the block that would be inside the block before the finally, then do the work in the finally block inside the objects destructor.

try {
   // Some work
}
finally {
   // Cleanup code
}

becomes

class Cleanup
{
public:
    ~Cleanup()
    {
        // Cleanup code
    }
}

Cleanup cleanupObj;

// Some work.

This looks terribly inconvenient, but usually there's a pre-existing object that will do the clean up for you. In your case, it looks like you want to destruct the object in the finally block, which means a smart or unique pointer will do what you want:

std::unique_ptr<Object> obj(new Object());

or modern C++

auto obj = std::make_unique<Object>();

No matter which exceptions are thrown, the object will be destructed. Getting back to RAII, in this case the resource allocation is allocating the memory for the Object and constructing it and the initialization is the initialization of the unique_ptr.

like image 64
David Norman Avatar answered Sep 18 '22 21:09

David Norman


No. The Standard way to build a finally like way is to separate the concerns (http://en.wikipedia.org/wiki/Separation_of_concerns) and make objects that are used within the try block automatically release resources in their destructor (called "Scope Bound Resource Management"). Since destructors run deterministically, unlike in Java, you can rely on them to clean up safely. This way the objects that aquired the resource will also clean up the resource.

One way that is special is dynamic memory allocation. Since you are the one aquiring the resource, you have to clean up again. Here, smart pointers can be used.

try {
    // auto_ptr will release the memory safely upon an exception or normal 
    // flow out of the block. Notice we use the "const auto_ptr idiom".
    // http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
    std::auto_ptr<A> const aptr(new A);
} 
// catch...
like image 37
Johannes Schaub - litb Avatar answered Sep 20 '22 21:09

Johannes Schaub - litb