tags:

views:

425

answers:

4

Hi,

Thanks for all the response.

I reformatted my question to understand the state of the member pointer after the containg class constructor throws an exception

Again my example class :)

class Foo
{
public:
    Foo()
    {
       int error = 0;
        p = new Fred;

        throw error;  // Force throw , trying to understand what will happen to p
    }

   ~Foo()
    {
       if (p)
       {
           delete p;
           p = 0;
       }
     }
private:
   Fred* p;
};

int main()
{
      try
      {
         Foo* lptr = new Foo;
      }
      catch (...)
      {}
}

The consturctor for class foo would throw an exception for some random reason. I understand that the desturctor of foo will never be called but in this case will the destructor for p get called?

what difference it makes to have p as a boost smart pointer than a raw pointer to fred.

Thanks.

+2  A: 

Not if it was never allocated.

But instead of NULL being returned by bad allocations via new, you will get an exception std::bad_alloc.

NULL gets returned by C malloc if an allocation cannot be made.

You are also correct that if an object is not fully constructed, it will not be destructed. So if you have a successful allocation on the heap in a constructor, and then an exception is thrown, that will lead to a memory leak.

You could also consider having a zombie state instead of throwing an exception. Some of the standard C++ library does this. In which case the object is not in a valid state and can be checked if it is in a valid state via another method.

Generally throwing exceptions in constructors is best though.

See my answer here for an extended discussion.

Brian R. Bondy
+1  A: 

The destructor for p will not be called, if the memory allocation for p fails.

Rob Knight
+1  A: 

The question really doesn't make any sense. new Fred(); will never return NULL. It will only ever either successfully create a Fred object, or throw an exception. If it threw an exception, the Fred object would never have existed, so it's destructor would not be called.

Tyler McHenry
'new' can return NULL if set_new_handler(NULL) was called beforehand, or if 'new(nothrow)' is used.
Remy Lebeau - TeamB
+1  A: 

There is a similar question here that covers what your asking.

In this case, if the call to new fails, then the memory for the pointer is guaranteed to be freed. If the call succeeds, and the constructor throws after that, you will have a memory leak.

The destructor of the class will not be called, because the object was never fully constructed. There are two ways to fix this.

1)

Have exceptions fully managed in the constructor:

class Foo
{
public:
    Foo()
    try
    {
        p = new p;

        throw /* something */; 
    }
    catch (...)
    {
       delete p;

       throw; //rethrow. no memory leak
    }
private:
    int *p;
};

2)

Or use a smart pointer. When a constructor is entered, all of its members have been constructed. And because when a constructor throws, and objects members have been constructed, they must be destructed. And a smart pointer fixes that:

class Foo
{
public:
    Foo() :
    p(new int)
    {
        throw /* something */; 
    }
private:
    std::auto_ptr<int> p;
};
GMan
Third way around the issue is two-phase construction. First phase: regular constructor that never throws. Second phase: possibly throwing code. Construction phases are easily integrated in a static factory method. This pattern is common in e.g. Symbian C++ code. http://developer.symbian.com/main/support/code_clinic/clinic_june2008/
laalto