Because the destructor of a class doesnt' run when its constructor throws - the object hasn't been fully initialized yet.
Also, you're not actually throwing std::exception
, but a pointer to it:
// dynamically allocates std::exception and throws a pointer to it
throw new std::exception("Exception thrown!");
EDIT: I noticed that you're catching a pointer, too, so that's not the problem. But, there's no constructor of std::exception
that takes a string literal, so I wonder how your code even compiles.
In any case, if a constructor can possibly throw after a raw resource has been allocated, you have a potential leak.
You need to wrap the resource in class that manages it - a smart pointer perhaps or a similar RAII wrapper. And use member initializer lists!
Another option is constructor delegation (new in C++11). An object is considered fully constructed when any of its constructors finishes execution. This means that if an exception is thrown from a constructor that delegated to another constructor (where you'd do the acquisition of handles), the destructor will be called.
To illustrate with some code:
struct Handle {
Handle() : handle(new int()) {}
~Handle() { delete handle; }
int* handle;
};
class MyClass {
Handle h;
MyFlass() : h() // handle initialized here
{
/**** code that may throw ****/
// this will properly close handles because
// the destructors of already initialized
// members (like h) will be called
}
~MyClass() { /* not called if constructor throws */ }
};
And an example of constructor delegation:
#include <iostream>
class MyClass {
private:
int* handle;
MyClass(int) // dummy parameter just for overloading
: handle(new int()) { /* better not throw from here */ }
public:
MyClass() : MyClass(0) // handle initialized here
{
/**** code that may throw ****/
throw 42;
}
~MyClass() { delete handle; std::cout << "dtor!"; }
};
int main()
{
try { MyClass m; } catch (int) {};
}
Output is dtor!
.