Throwing exceptions from a constructor is a good thing. When something fails in a constructor, you have two options:
- Maintain a "zombie" state, where the class exists but does nothing, or
- Throw an exception.
And maintaining zombie classes can be quite a hassle, when the real answer should have been, "this failed, now what?".
According to the Standard at 3.6.2.4:
If construction or destruction of a non-local static object ends in throwing an uncaught exception, the result is to call terminate (18.6.3.3).
Where terminate refers to std::terminate
.
Concerning your example, no. This is because you aren't using RAII concepts. When an exception is thrown, the stack will be unwound, which means all objects get their destructor's called as the code gets to the closest corresponding catch
clause.
A pointer doesn't have a destructor. Let's make a simple test case:
#include <string>
int main(void)
{
try
{
std::string str = "Blah.";
int *pi = new int;
throw;
delete pi; // cannot be reached
}
catch(...)
{
}
}
Here, str
will allocate memory, and copy "Blah." into it, and pi
will be initialized to point to an integer in memory.
When an exception is thrown, stack-unwinding begins. It will first "call" the pointer's destructor (do nothing), then str
's destructor, which will free the memory that was allocated to it.
If you use RAII concepts, you'd use a smart pointer:
#include <memory>
#include <string>
int main(void)
{
try
{
std::string s = "Blah.";
std::auto_ptr<int> pi(new int);
throw;
// no need to manually delete.
}
catch(...)
{
}
}
Here, pi
's destructor will call delete
and no memory will be leaked. This is why you should always wrap your pointers, and is the same reason we use std::vector
rather than manually allocating, resizing, and freeing pointers. (Cleanliness and Safety)
Edit
I forgot to mention. You asked this:
I think I want to put an autoptr around P and call release on the autoptr after dostuff to prevent a memory leak, would that be correct?
I didn't state it explicitly, and only implied it above, but the answer is no. All you have to do is place it inside of auto_ptr
and when the time comes, it will be deleted automatically. Releasing it manually defeats the purpose of placing it in a container in the first place.
I would also suggest you look at more advanced smart pointers, such as those in boost. An extraordinarily popular one is shared_ptr
, which is reference counted, making it suitable for storage in containers and being copied around. (Unlike auto_ptr
. Do not use auto_ptr
in containers!)