Member destructor inside a constructor

G

gurry

Suppose there's a class A. There's another class called B which looks
like this:

class B {
private:
A a;
public :
B() { a.~A() }
}

Notice that B has a member 'a' which is an instance of class A. Also
notice that the default constructor of B calls the destructor of 'a'.

Let's now use class B in a main() block:

void main() {
B obj;
}

My question is: when this main() is run, what happens?

Well, I myself have compiled and run this code and I found that the
destructor of 'a' is called twice: first when 'obj' is constructed
(because class B's constructor calls 'a's destructor explicitly) and
second time when the control exits the main() block and 'obj' is
destroyed by calling class B's destructor.

Now if 'a' has already been destroyed in class B's constructor, how can
'a''s destructor be called again through class B's destructor? Does
that mean that even after 'a's destructor is called in class B's
construtor, it isn't actually destroyed?

My motive for this experiment is to know what to do when you want to
throw exceptions from a constructor of any class and you want to
properly destroy all its member objects before the exception is thrown.
Is calling members' destructors like I did above a right way to achieve
this?

Thanks in advance,
Gurry
 
A

anubis

Well, if destructor of A class does nothing with freeing objects, then
it's just calling any other method.
So if destructor of A is empty, then it doesn't do anything, and a is
destroyed when class B is destroyed.

I guess :)
 
C

Catalin Pitis

gurry said:
Suppose there's a class A. There's another class called B which looks
like this:

class B {
private:
A a;
public :
B() { a.~A() }
}

Notice that B has a member 'a' which is an instance of class A. Also
notice that the default constructor of B calls the destructor of 'a'.

Let's now use class B in a main() block:

void main() {
B obj;
}

My question is: when this main() is run, what happens?

I happens the following:
B::B()
A::A()
A::~() // your explicit call
B::~B() // called automatically, since the scope of obj ended
A::~A() // called by the generated destructor of class B

When an exception is thrown from the constructor, you should take care
of deallocating the resources (e.g. memory) you allocated at
construction time, before throwing the exception, because no destructor
of the class will be called (because the object is considered as
constructed only after the complete execution of the constructor).

Catalin
 
M

Michiel.Salters

gurry said:
Suppose there's a class A. There's another class called B which looks
like this:

class B {
private:
A a;
public :
B() { a.~A() }
}

Notice that B has a member 'a' which is an instance of class A. Also
notice that the default constructor of B calls the destructor of 'a'.

Let's now use class B in a main() block:

void main() {
B obj;
}

My question is: when this main() is run, what happens?

The compiler barfs on void, I guess. It's int main() { }
After that, the program will have Undefined Behavior when B::~B() is
called. The destructor always destroys every member, which isn't
possible here. Anything may happen at that point.

HTH,
Michiel Salters
 
B

benben

gurry said:
Suppose there's a class A. There's another class called B which looks
like this:

class B {
private:
A a;
public :
B() { a.~A() }
}

Notice that B has a member 'a' which is an instance of class A. Also
notice that the default constructor of B calls the destructor of 'a'.

Let's now use class B in a main() block:

void main() {
B obj;
}

My question is: when this main() is run, what happens?

That would cause the program to call A::~A on a destroyed object, which
is Undefined Behavior I believe. Don't do it.
Well, I myself have compiled and run this code and I found that the
destructor of 'a' is called twice: first when 'obj' is constructed
(because class B's constructor calls 'a's destructor explicitly) and
second time when the control exits the main() block and 'obj' is
destroyed by calling class B's destructor.

Good! Exactly what should happen! But you are also lucky (or unlucky)
that the program didn't crash.
Now if 'a' has already been destroyed in class B's constructor, how can
'a''s destructor be called again through class B's destructor? Does
that mean that even after 'a's destructor is called in class B's
construtor, it isn't actually destroyed?

The member is indeed destroyed in B's constructor. But the compile would
have no clue whether the member is destroyed or not--it won't bother to
fathom your call to the destructor.

All members are automatically destroyed upon destruction of their
parent. If any of them has a non-trivial destructor it will be called.
Simple as that.
My motive for this experiment is to know what to do when you want to
throw exceptions from a constructor of any class and you want to
properly destroy all its member objects before the exception is thrown.
Is calling members' destructors like I did above a right way to achieve
this?

You can't test it, just as you can't predict the future. Calling the
destructor before hand you won't give you the answer. Consider:

// Flawed example
class not_so_nice
{
public:
~not_so_nice()
{
bool n;
cin >> n;
if (n) throw n;
}
};

class cynic
{
not_so_nice nsn;
public:
cynic()
{
nsn.~not_so_nice(); // test destructor
new(&nsn) not_so_nice; // reconstruct member
}
};

int main()
{
cynic c;
}// oops, can still throw from destructor

Since you can't predict the user input you can't test the behavior of
~not_so_nice.

Generally, destructors don't throw. It is not worth protecting from
extreme cases.

On the other hand, if you are required to be absolutely exception proof
for destruction, you can mandate the member to provide no throw function
for destruction, for example:

class safe_selfdestructor
{
public:
virtual void destroy_self(void) throw() = 0;
};

class example: public safe_selfdestructor
{
public:
void destroy_self(void) throw(){delete this;}

~example()
try
{
// ...
}
catch (...){} // hide exception
};

class cynic
{
example* p_ex;
safe_selfdestructor* p_des;
public:
cynic(){p_ex = new example; p_des = p_ex;}
~cynic(){p_des->destroy_self();}
};

Beware that trying to hide a thrown exception can be more dangerous then
letting it crash your program. You have been warned.

Thanks in advance,
Gurry

Regards,
Ben
 
B

Bronek Kozicki

gurry said:
class B {
private:
A a;
public :
B() { a.~A() }
}

that's an undefined behaviour. Unfortunatelly, in most situations you
will not see a crash


B.
 
G

gurry

Thank you all guys. This clears up things a bit.

And benben thanks for the detailed post but I guess you read me wrong.
I intend to throw an exception from a constructor not a destructor
(which I think is more often the case, though I'm not sure).

So the question remains: how do you gracefully destroy member objects
already created by the constructor before you throw an exception. In my
post, I tried explict calls to the destructors of the already created
member objects, which, as it is confirmed by you guys, is not a good
practice. Then how do you achieve the graceful destruction of member
objects?

I read one way to do it in the Bruce Eckel book that involved having
pointers to objects as members instead of the objects themselves. But
pointers are not always possible to have. What if I am required to have
a vector of some, say, userdefined class objects as a member of my
class? How would I make sure that this vector's destructor is called
before throwing an exception?

Thanks in advance.
gurry
 
A

AnalogFile

gurry said:
Thank you all guys. This clears up things a bit.

And benben thanks for the detailed post but I guess you read me wrong.
I intend to throw an exception from a constructor not a destructor
(which I think is more often the case, though I'm not sure).

So the question remains: how do you gracefully destroy member objects
already created by the constructor before you throw an exception. In my

Just don't. The compiler will do it automagically.
 
I

iftekhar

First of all , the call a::~A() does not destroy the object a. it is
merely a function call. Only the constructor cannot be called
explicitly in a C++ program. Generally, the intent of calling the
destructor explicitly is to cleanup and reuse the object. The
destructor is call twice because it was called once explicitly and
then automatically by the compiler as the destruction sequence of B.

far as i know the behaviour is NOT undefined. check out the ISO
standard.
My motive for this experiment is to know what to do when you want to
throw exceptions from a constructor of any class and you want to
properly destroy all its member objects before the exception is thrown.
Is calling members' destructors like I did above a right way to achieve this?

it is guranteed by the C++ standard, far as i know, that inside a
constructor, any member object created "Completely" in the stack will
destroyed if the constructor throws. For dynamically created objects
(with new) you have to take cate of that. If you face something like
this, consider using auto pointer (std::auto_ptr<>) or use a two stage
construction (i.e. constructor does nothing and a function like
initialize() does the logical construction of the object).

I hope it was of some help

cheers
Iftekhar
 
K

Kai-Uwe Bux

iftekhar said:
First of all , the call a::~A() does not destroy the object a. it is
merely a function call.

Nope: the call to the destructor ends the lifetime of the object [3.8/4].
All subsequent operations on the object are undefined behavior (including a
second call to the destructor). Well-defined are only operations that refer
to the objects location in memory as raw memory [3.8/5].

Only the constructor cannot be called
explicitly in a C++ program. Generally, the intent of calling the
destructor explicitly is to cleanup and reuse the object.

Nope: "Generally", you don't call the destructor explicitly. Specifically,
if you do so, then you are very likely writing an allocator class and your
explicit destructor calls match some calls to placement new (the standards
hook to construct an object at a given location in memory -- as close to an
explicit constructor call as you can get).

In other words: you cannot reuse the object (because it's dead). You can,
however, reuse the memory occupied by the objects dead body. To accomplish
this, you can construct a new object in the same place by calling placement
new.

The destructor is call twice because it was called once explicitly and
then automatically by the compiler as the destruction sequence of B.

far as i know the behaviour is NOT undefined.

Nope: it is undefined [12.4/14].

check out the ISO standard.

Good advice!


[snip]


Best

Kai-Uwe Bux
 
A

AnalogFile

iftekhar wrote:
....
it is guranteed by the C++ standard, far as i know, that inside a
constructor, any member object created "Completely" in the stack will
destroyed if the constructor throws. For dynamically created objects
(with new) you have to take cate of that.

Nope. If the *constructor* throws, it is guaranteed that any sub-object
that was completely constructed is destructed and that the deallocator
function is called to free up the memory that was allocated. If the
deallocator function exists, of course.
 
G

gurry

Thanks a lot guys. Now I know: if my class holds a 'sub-object' then
its destructor will surely be called when my class's constructor throws
exception, but if my class has a *pointer* to a 'sub-object', then
that's my own responsibility to clean up.

Thanks for the discussion.
 
I

iftekhar

Hi,
Thanks a lot. I completely forgot about the placement new that should
(must??) be used with the explicit destructor calls. Thanks again for
the refresh :D.
cheers
Iftekhar
 
I

iftekhar

AnalogFile said:
Nope. If the *constructor* throws, it is guaranteed that any sub-object
that was completely constructed is destructed

That is exactly what i ment.
and that the deallocator
function is called to free up the memory that was allocated. If the
deallocator function exists, of course.

far as i know, the deallocator (assuming destructor) will not be called
since the object creation was not "complete"ed. The base class
destructors will be called though (if they were created completely).
fro this reason there is somthing called "function-try-block".
class foo
{
private:
char* p;
char* q;
public:
foo (void)
try
{ : p(new char[100]),
q(new char[100])
{
...
}
}
catch(bad_alloc ??)
{
delete p;
delete q;
}
}
even that does not help here, since you cant tell whether the p or q
allocation failed.

correct me if i am wrong.

cheers
iftekhar
 
P

Puppet_Sock

gurry wrote:
[snip]
My motive for this experiment is to know what to do when you want to
throw exceptions from a constructor of any class and you want to
properly destroy all its member objects before the exception is thrown.
Is calling members' destructors like I did above a right way to achieve
this?

When exceptions are thrown the stack gets unwound till the
exception is caught. So, if each class has appropriate things
to give back resources in its dtor, you don't want to be
explicitly calling dtors. That is, any problems you could
theoretically have avoided by explicitly calling a dtor would
automatically be avoided by stack unwinding. And any
probs that you would get into through stack unwinding
would be made no better by explicitly calling the dtor.

So, for example: Suppose you run out of memory, and then
the stack unwinding fails because of that. I don't know,
maybe a dtor needs a temp variable to run properly, and
does not have room to make it, so the dtor fails. Now you
have big trouble in code land. But explicitly calling the
dtor does not make this any bette, in fact it could be
worse.

So, explicitly calling a dtor is usually a bad idea.
Socks
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top