catch exception

J

junw2000

class A
{
public:
A()
{
try
{
p = new int;
//Other lines that may throw exception.
}
catch(...)
{
delete p;
}

private:
int *p;
};

In the above code, catch the exception in A's constructor to delete p.
Is it OK? Is there a better way to delete p?

Thanks.

Jack
 
A

Andre Kostur

(e-mail address removed) wrote in (e-mail address removed):
class A
{
public:
A()
{
try
{
p = new int;
//Other lines that may throw exception.
}
catch(...)
{
delete p;
}

private:
int *p;
};

In the above code, catch the exception in A's constructor to delete p.
Is it OK? Is there a better way to delete p?

It will work... what would be better is to use some sort of smart pointer
class, such as std::auto_ptr. Assuming you need the dynamic allocation in
the first place (In this simple example, it makes no sense to make p
dynamic at all...)

Example:


class A
{
public:
A() : p(new int)
{
// Other potentially throwing code
}

private:
std::auto_ptr<int> p;
};
 
R

red floyd

class A
{
public:
    A()
    {
         try
         {
               p = new int;
               //Other lines that may throw exception.
         }
         catch(...)
         {
               delete p;
         }

private:
     int *p;

};

In the above code, catch the exception in A's constructor to delete p.
Is it OK? Is there a better way to delete p?

Yes it's OK (modulo the missing closing brace), but better is:

class A
{
public:
A() : p(new int(0))
{
// do other stuff which may throw
}

private:
some_smart_pointer_type<int> p;

};

Now if that stuff throws, the smart pointer for p will be destroyed,
which will delete p.
Pick your smart pointer -- see boost and tr1. Or, if you know this
object won't be getting copied, or you have a deep copy constructor,
you could use std::auto_ptr
 
G

gpderetta

class A
{
public:
A()
{
try
{
p = new int;
//Other lines that may throw exception.
}
catch(...)
{
delete p;
}

private:
int *p;

};

If 'new int' throws, you'll be deleting an uninitialized pointer which
is UB.
It is safer and simpler to use a smart pointer.

HTH,
 
J

Juha Nieminen

Andre said:
(e-mail address removed) wrote in (e-mail address removed):


It will work...

Really? What will be the value of p if 'new' throws?

Wouldn't it be better like this:

A(): p(0)
{
try
{
p = new int;
}
catch(...)
{
delete p;
}
}
 
J

Joe Greer

Really? What will be the value of p if 'new' throws?

Wouldn't it be better like this:

A(): p(0)
{
try
{
p = new int;
}
catch(...)
{
delete p;
}
}

It depends upon what you are after, In the previous case, if new
throws, p is never assigned a value and A is never constructed. If all
of your resources are wrapped in RAII classes (such as auto_ptr), then
anything constructed prior to the new throwing will be cleaned up as the
exception leaves A's constructor. This is all done for you. The code
you provided really doesn't do anything. If the new throws, then p
won't need deleted. If the new works, then it won't be deleted. If you
didn't want the new to prevent the construction of A, then you could do
something like:

A()
{
try
{
std::auto_ptr<int> p(new int);
//do stuff with p
// p gets automatically deleted as it leaves this scope.
} catch(...)
{ // don't really care if the above worked or not
}

// do other stuff
}

-or-

A()
{
try
{
p.reset(new int);
//do stuff with p
// p gets automatically deleted when A gets deleted.
} catch(...)
{ // don't really care if the above worked or not
}

// do other stuff
std::auto_ptr<int> p;
}


Both of these would prevent the allocation of p from preventing the
construction of A (though if you are really that low on memory, do you
really want to carry on?) and will automatically handle the deletion of
the object when A is destroyed.

Generally speaking (meaning there are always special cases) I think
Andre's solution is the cleanest for most uses.


joe
 
J

junw2000

If 'new int' throws, you'll be deleting an uninitialized pointer which
is UB.
It is safer and simpler to use a smart pointer.

HTH,

In fact, smart pointer will also delete p. Theoretically, they are the
same, rigth?

Jack
 
G

gpderetta

In fact, smart pointer will also delete p.

The smart pointer will not delete 'p', 'p' will be the smart pointer :

struct A() {

A() p(new int) { /* do something with p */ }
private:
Theoretically, they are the
same, rigth?

Wrong. If 'new int' trows, the smart pointer won't have been
constructed yet, so its destructor won't be called.

OTOH, if you instead reset p to 'new int' in the body of the
constructor, the smart pointer will have been default constructed. If
'new int' throws, p destructor will be called, but destroying a
default constructed smart pointer will not lead to UB (well, at least
for any reasonable smart pointer).

In general, the less you use try/catch, the easier is not to make
mistakes. RAII is your friend.

HTH,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top