1
int main(){
   //Node is some template class
   Node<int>* head = new Node<int>[5];

   for(int ii = 0; ii < 5; ii++)
   {
      head[ii].set_Data(ii);
      head[ii].set_Link(head + (ii + 1));
      if(ii == 4)
      {
        head[ii].set_Link(NULL);
      }
   }
   delete [] head;
 }


template<typename T>
void Node<T>::set_Link(Node* Node_Address)
{
    Link = Node_Address;
}


template<typename T>
Node<T>::~Node()
{
    delete Link;
    cout << "Destructor" << endl;
}

I'm learning linked lists right now. I don't get why my destructor is called 15 times and cout statement is printed 15 times. If I get rid of the statement

head[ii].set_Link(head + (ii + 1));

The destructor is only called 5 times, which makes sense since 5 classes are made. Why is the destructor called when I use the member function set_Link(), when I am only passing a pointer, not a class. The copy constructor isn't even called. Thanks for any help!

Jimmy Wong
  • 21
  • 2
  • "Why is the destructor called when I use the member function set_Link()." - it doesn't get called. you're already doing some trace messages, add some more. I wonder how you failed to notice this. – Karoly Horvath Jul 24 '12 at 06:28
  • Please post a complete but minimal program that demonstrates this behavior. Otherwise, all we can do is guess, and that would not be helping you. – Björn Pollex Jul 24 '12 at 06:29
  • Please post the exact output in either case you are describing. What is the code of `set_Data`? – Jakob S. Jul 24 '12 at 06:30

3 Answers3

8

You have UB here. The destructors are called multiple times. delete [] head; calls the destructor of each object in the array. The destructor in turn calls the destructor of the linked object through delete Link;.

In total destructors are called 5 + 4 + 3 + 2 + 1 = 15 times. Mostly on already destroyed objects.

Normally, you wouldn't create an array for the elements of a linked list. Instead, create the list like this:

Node<int>* head = new Node<int>(); 
Node<int>* node = head;
for(int ii = 0; ii < 5; ii++) 
{ 
  node->set_Data(ii); 
  if(ii == 4) 
  { 
    node.set_Link(NULL); 
  }
  else
  {
    Node<int>* next = new Node<int>();
    node->set_Link(next);
    node = next;
  }
} 
delete head; 
Henrik
  • 23,186
  • 6
  • 42
  • 92
  • Thanks. I added cout statement before "delete link" as Karoly suggested,and it the message came out as you predicted the destructors would be called. I would not have guessed that behavior. I'll remember that when creating new lists, is there a particular reason why an array would be bad for initializing a list though? – Jimmy Wong Jul 24 '12 at 07:31
  • @JimmyWong: you use a linked list when you need the ability to add/remove nodes at random positions. This is not so easy if the elements are stored in an array. – Henrik Jul 24 '12 at 07:40
  • 1
    @cojocar UB = undefined behavior http://stackoverflow.com/questions/2766731/what-exactly-do-ib-and-ub-mean – Henrik Jun 11 '13 at 07:04
1

In the linked list node destructor you don't want to delete the pointed next node. That will cascade delete all the tail nodes. You could prevent it by setting the pointer to NULL first, but that is just a maintainability nightmare, and it will create a lot of subtle bugs like this.

Note: "Why is the destructor called when I use the member function set_Link()" - It doesn't get called, and it's very easy to verify this by adding a couple of extra trace messages. All destructor calls originate from that one delete [] call.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
1

The full array of five Nodes is created via new, that's ok. But the pointers you pass to set_Link() point to somewhere inside this memory block, so (a) the heap manager doesn't know how to handle them when your destructor calls delete Link; and (b) even if it would know, they get deleted multiple times as your five objects thy to delete each other.

As a note: You only need to delete something you obtained via new.

C. Stoll
  • 376
  • 1
  • 6
  • Thanks, noted about the delete, I misread something off my textbook. You're right, removing the "delete link" the program is behaving more predictably now and the destructor is called only 5 times now. – Jimmy Wong Jul 24 '12 at 07:17