Can I delete without calling the destructor ?

T

Timothy Madden

Hello

I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

How can I delete an element, from the destructor, without calling the
destructor again ?

Thank you
Timothy Madden
Romania
 
H

Howard

Timothy Madden said:
Hello

I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

I'm not sure what you mean when you say you don't want to "recursively"
destroy the elements. Generally, you'd use a loop to delete a list's
elements, not recursion.

(Now, if you *wanted* recursion, you could have the destructor just call
"delete Next;", so that each element deleted the following element. The
last one would be calling delete on a NULL pointer, which is a no-op, and
would end the recursion.)
class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

How can I delete an element, from the destructor, without calling the
destructor again ?

I don't think this idea, even if you can find a way to do it, would be a
very good way to do things. Why not use a loop *outside* the destructor, to
destroy the list elements. The best place for it would be in the destructor
of the class that encapsulates the list itself (i.e., the one that owns the
pointer to the first element in the list). If you just have this list
residing in main, and not in a class, I'd recommend putting it in a class
instead, and then putting the loop in that class' destructor.

-Howard
 
V

Victor Bazarov

Timothy said:
I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

class ListElem
{
char Datum[1000];
class ListElem *Next;
^^^^^
No need for keyword 'class' here.
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
^^^^^
No need for keyword 'class' here either.
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

A recursive call to the destructor is no big deal, AFAICT. To avoid
multiple deletions (I presume that's what you're experiencing) you do

~ListElem()
{
delete Next;
}

That should take care of the whole list. If the element being deleted
has 'Next' a null pointer, 'delete 0' does nothing and your recursion
returns.
How can I delete an element, from the destructor, without calling the
destructor again ?

Victor
 
T

Timothy Madden

Victor Bazarov said:
Timothy said:
class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

A recursive call to the destructor is no big deal, AFAICT. To avoid
multiple deletions (I presume that's what you're experiencing) you do

~ListElem()
{
delete Next;
}

That should take care of the whole list. If the element being deleted
has 'Next' a null pointer, 'delete 0' does nothing and your recursion
returns.

I don't want to recursively destroy the list; the list is arbitrary long.
Any 'delete Next' in the desctructor will recursivly call the destructor;
What if the list is 10000 or 100000 or 1000000 elements ?
 
T

Timothy Madden

Howard said:
I'm not sure what you mean when you say you don't want to "recursively"
destroy the elements. Generally, you'd use a loop to delete a list's
elements, not recursion.

I mean I don't wanna do

ListElem::~ListElem()
{
delete Next;
}

and that I want a loop. But in a loop I still have to use delete and that's
the
problem.
I don't think this idea, even if you can find a way to do it, would be a
very good way to do things. Why not use a loop *outside* the destructor, to
destroy the list elements. The best place for it would be in the destructor
of the class that encapsulates the list itself (i.e., the one that owns the
pointer to the first element in the list). If you just have this list
residing in main, and not in a class, I'd recommend putting it in a class
instead, and then putting the loop in that class' destructor.
There is no class that encapsulates the list. All you need is an element of
the list and you really have a list. I hope you agree it is much simple like
this.
Of course a haviley used list needs a santinel for performance and so it
needs an encapsulating class but right now I just need to do things and to
do them simple.

That is, when I'll write the proper destructor ...
 
V

Victor Bazarov

Timothy said:
Timothy said:
class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

A recursive call to the destructor is no big deal, AFAICT. To avoid
multiple deletions (I presume that's what you're experiencing) you do

~ListElem()
{
delete Next;
}

That should take care of the whole list. If the element being deleted
has 'Next' a null pointer, 'delete 0' does nothing and your recursion
returns.


I don't want to recursively destroy the list; the list is arbitrary long.
Any 'delete Next' in the desctructor will recursivly call the destructor;
What if the list is 10000 or 100000 or 1000000 elements ?

You probably don't understand the importance of destructors. They define
the lifetime of objects. You cannot dispose of an object without invoking
or calling its destructor.

If you don't want to recursively destruct your list, don't define it the
way you defined it: recursively. In your list 'ListElem' is the _head_
of the list, and ListElem::Next is the _head_of_the_tail_ of that list.

ListElem essentially _is_ the list. And since destroying the list means
destroying its head _plus_ destroying its tail, that's what you have to
do. If your list is arbitrarily long, it still all has to be destroyed.

Victor
 
R

Rubén Campos

Timothy Madden said:
Hello

I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

How can I delete an element, from the destructor, without calling the
destructor again ?

Thank you
Timothy Madden
Romania

I agree with Victor Bazarov, in the fact that your problem comes from a bad
design of your list. Yes, it seems to be simpler, faster and clearer, but
that is not truth, and your problem is enough prove of this. The
(simple-linked) list is an entity itself, and so it should be implemented as
a class other than ListElem. Though an element provides the functionality to
organize it inside a list, it's not the entire list, but just a single
element.

Also, you should consider a third class, an iterator, which manages a single
traversal over the list. Because you can have an arbitrary number of
simultaneous traversals over a same list, this functionality can not be
included inside the list itself (and again, it's not responsibility of a
single element).

Last, think that a single-linked list is one of the simplest data
structures. Things I comment here gain in relevance as the complexity levels
grows up.

But returning to your question, here is a solution which deletes the entire
list in the way that you want to do it, avoiding those problems derived from
recursion. There is still a recursion, which is unavoidable with your
scheme, but it's only a two-level recursion.

~ListElem()
{
ListElem * el;

while (Next)
{
el = Next;
Next = Next->Next;
el->Next = NULL; // This is enough to ensure that the list will
be not recursively traversed.
delete el;
}
}
 
J

John Harrison

There is no class that encapsulates the list. All you need is an element
of
the list and you really have a list. I hope you agree it is much simple
like
this.
Of course a haviley used list needs a santinel for performance and so it
needs an encapsulating class but right now I just need to do things and to
do them simple.

Not at all, its bad design. It causes confusion between operations on the
nodes of the list (which the user should not have to care about) and
operations on the list itself (which the user does care about). In fact this
is exactly the confusion you have yourself and you are writing the list!

Write a class that encapsulates the list, this is what OO is all about.

john
 
J

John Harrison

You probably don't understand the importance of destructors. They define
the lifetime of objects. You cannot dispose of an object without invoking
or calling its destructor.

If you don't want to recursively destruct your list, don't define it the
way you defined it: recursively. In your list 'ListElem' is the _head_
of the list, and ListElem::Next is the _head_of_the_tail_ of that list.

ListElem essentially _is_ the list. And since destroying the list means
destroying its head _plus_ destroying its tail, that's what you have to
do. If your list is arbitrarily long, it still all has to be destroyed.

Victor

I think the OP is worried about blowing the stack during list destruction.

john
 
R

R.ealname

Timothy Madden said:
Hello

I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;

Insert
el->Next = 0;

here. Could be very useful :)
 
T

Timothy Madden

Rubén Campos said:
Timothy Madden said:
Hello

I have a linked list of object of a class. I thought it would be nice to
have the destructor delete the whole list when I delete just the first
element. I don't want to recursivly destroy the list elements; the list is
arbitrary long. Something like this:

class ListElem
{
char Datum[1000];
class ListElem *Next;
ListElem()
{ Next = NULL; }
~ListElem()
{
class ListElem *el;
while (Next)
{
el = Next;
Next = Next->Next;
delete el;
}
}
}

but the last instruction delete el; will make a recursive call to the
destructor and it's all going down.

---------------------------------------------


~ListElem()
{
ListElem * el;

while (Next)
{
el = Next;
Next = Next->Next;
el->Next = NULL; // This is enough to ensure that the list will
be not recursively traversed.
delete el;
}
}

Indeed it is so !!!!!!
Thank you very much !!
By myself, I ended up with a static flag inside the
destructor to stop recursion.

But el->Next = NULL is the real answer

Thank you
Timothy Madden
Romania
 
O

Old Wolf

R.ealname said:
Insert
el->Next = 0;

here. Could be very useful :)

Not. 'el' is deleted in the very next instruction, so that assignment
is worthless, a good compiler would optimise it out.
 
V

Victor Bazarov

Old said:
Not. 'el' is deleted in the very next instruction, so that assignment
is worthless, a good compiler would optimise it out.

It is often useful to read the entire thread before barging in.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top