throwing exception from constructor .

M

mangesh

I read , FAQ : 17.4] How should I handle resources if my constructors
may throw exceptions?

Above faq says that use smart pointer in construcors . Because if
exception is thrown from constructor it's destructor is not run .So to
avoid memory lekage use smart pointer .
But if exception is thrown we can release resources in catch block . So
use of smart pointer is not must , we have this secnd option . Am i
right ?
 
V

Victor Bazarov

mangesh said:
I read , FAQ : 17.4] How should I handle resources if my constructors
may throw exceptions?

Above faq says that use smart pointer in construcors . Because if
exception is thrown from constructor it's destructor is not run .So to
avoid memory lekage use smart pointer .
But if exception is thrown we can release resources in catch block .
So use of smart pointer is not must , we have this secnd option . Am i
right ?

You can release in a catch block, unless you lose track of the resource
to be released. If it's a local object in the body of the construct,
how do you know its value to release in the catch block?

V
 
B

Ben Pope

mangesh said:
I read , FAQ : 17.4] How should I handle resources if my constructors
may throw exceptions?

Above faq says that use smart pointer in construcors . Because if
exception is thrown from constructor it's destructor is not run .So to
avoid memory lekage use smart pointer .
But if exception is thrown we can release resources in catch block . So
use of smart pointer is not must , we have this secnd option . Am i
right ?

Consider:
class ResourceHolder {
int* pointer1;
int* pointer2;
// prevent copy and assignment
ResourceHolder(const ResourceHolder&);
ResourceHolder& operator=(const ResourceHolder&);
public:
ResourceHolder() : pointer1(new int(1)), pointer2(new int(2)) {}
~ResourceHolder() {
delete pointer1;
delete pointer2;
}
}

The line:
ResourceHolder r;

Requires allocation of 2 ints, either of which could fail and throw an
exception. The problem is: which one failed?

If you change the constructor to include try catch:
ResourceHolder() : pointr1(0), pointer2(0) {
// if this throws, it's ok
pointer1 = new int(1);
try {
// if this throws, clean up pointer 1
pointer2 = new int(2);
} catch () {
delete pointer1;
}
}

That's starting to get a bit messy, imagine scaling that to 5 resources,
it's better to apply RAII to all resources, and just use a smart
pointer, even if it's just std::auto_ptr<int>.

It's much less error prone.

Ben Pope
 
M

Markus Schoder

mangesh said:
can't we call destructor explicitly in catch block ?

Yes you can.

The following should work just fine but in general it might be not
trivial to ensure that the destructor can be safely called for a
partially constructed object. E.g. in this case the initialization of
the pointers to 0 is crucial.

ResourceHolder() : pointer1(0), pointer2(0) {
try {
pointer1 = new int(1);
pointer2 = new int(2);
} catch(...) {
this->ResourceHolder::~ResourceHolder();
throw;
}
}
 
B

Ben Pope

mangesh said:
can't we call destructor explicitly in catch block ?

It's not advisable to delete something that was not allocated. If
pointer1 fails allocation, and you call the destructor, you will delete
two objects that were not allocated. Of course, if the pointers were
initialised to 0, then calling delete on them is ok.

What do you have against auto_ptr? It does the job you require, with
neat and safe syntax. Use it.

Ben Pope
 
M

Markus Schoder

Ben said:
What do you have against auto_ptr? It does the job you require, with
neat and safe syntax. Use it.

auto_ptr as member is generally not advisable because of its odd copy
semantics. You can of course use it locally and then assign to the
actual member later:

auto_ptr<int> p1 = new int(1);
auto_ptr<int> p2 = new int(2);

// ... other stuff that might throw ...

pointer1 = p1.release();
pointer2 = p2.release();
 
B

Ben Pope

Markus said:
auto_ptr as member is generally not advisable because of its odd copy
semantics.

Not much more odd than a pointer, it won't get you into any more
trouble, besides, in my example I had disabled copying. This is fairly
common in classes that manage resources.

The point is that there are tools to help, the OP should use them.

Ben Pope
 
M

Markus Schoder

Ben said:
Not much more odd than a pointer, it won't get you into any more
trouble, besides, in my example I had disabled copying. This is fairly
common in classes that manage resources.

auto_ptr has a copy constructor that modifies the _source_. This is as
odd as it gets in my book.
 
C

Cy Edmunds

Markus Schoder said:
auto_ptr has a copy constructor that modifies the _source_. This is as
odd as it gets in my book.

I agree. IMHO auto_ptr should never be used as a member in a class. No
matter how carefully you document the resulting behavior, when somebody
writes

y = x;

and it changes x, confusion if not disaster is likely to follow.

boost::shared_ptr doesn't have this problem.

Cy
 
D

Diego Martins

Cy said:
I agree. IMHO auto_ptr should never be used as a member in a class. No
matter how carefully you document the resulting behavior, when somebody
writes

y = x;

and it changes x, confusion if not disaster is likely to follow.

boost::shared_ptr doesn't have this problem.

Cy

shared_ptr is slower :)

and unnecessary using move semantics

any class with move semantics can use auto_ptr without problems :)
 
M

Michiel.Salters

Cy said:
IMHO auto_ptr should never be used as a member in a class. No
matter how carefully you document the resulting behavior, when somebody
writes

y = x;

and it changes x, confusion if not disaster is likely to follow.

Nonsense. BY that argument, raw pointers shouldn't be used in classes,
because after y = x, changing x shouldn't change y.
Of course, that doesn't happen with real classes using raw pointer,
because
they copy the pointed-to object and not the pointer. The same applies
to
auto_ptr members. Your copy ctor will simply copy the pointed-to
object,
and not change the source auto_ptr. You usually can't, because inside
your copy ctor the source auto_ptr is const (assuming X::X(X const&
src)

HTH,
Michiel Salters
 

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,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top