Sdílet prostřednictvím


Simulating try/finally in plain C++ (without the C++/CLI extensions)

Dan wrote:

I think this is close enough to try/finally in C++:

Resource* pRes = new Resource;
try
{
  // use the allocated resource somehow
}
catch (...)
{
  delete pRes;
  throw;
}

First, note that this code as written doesn't do "finally," because the idea behind a finally block is that it gets executed whether an exception is thrown or not. But it's close: You can indeed get a similar effect if you add a throw statement (e.g., throw 1;) at the end of your try block, so that it always exits via an exception, and then catch(...).

Even after applying the quick fix to make this do what was intended, this (ab)use of the try/catch mechanism inferior to having finally (or better still, in most cases, a destructor) because it interacts poorly with other exceptions. For example, what if other parts of the body could throw specific exceptions we want to catch? It would be repetitive and fragile to duplicate the delete statement in every catch block. Also, it's going to be more expensive in runtime cost because an exception will always be thrown, and actually throwing an exception has nonzero cost on every implementation I've heard of; having finally just has the compiler ensure the given code runs in all cases without having to throw an extra exception if none was otherwise being thrown.

Comments

  • Anonymous
    September 06, 2004
    This is how I simulate try...finally

    {//start a dummy block
    //Allocate resources here

    class Finalizer
    }
    public:
    ~Finalizer()
    {
    //Release all resources here
    }
    };
    Finalizer finally;

    try
    {
    }catch (Type1 t1)
    {
    //do stuff
    }
    }
    //'finally' gets destroyed here if
    //no exception is thrown. If an uncaught
    //exception is thrown, all locals are destroyed
    //which includes 'finally' also. So resources
    //are released in any case
  • Anonymous
    September 12, 2004
    What Vatsan said. Do your clean up in the destructor. Seeing as the CLI/CLR is written in plain old C++ there really isn't anything it can do that regular C++ can't. There is a lot regular C++ can do however that the CLI/CLR can't. That is the case with all wrappers though. Wrappers make your work faster to code but you are limited by the interface. With the CLI/CLR MS tried to write a big enough wrapper that people won't feel constrained. They did a pretty good job but in the end it is still a wrapper ( or interface if you like ).