2

I am having a problem with std::list.

std::list<Component*> mComponents;
//add some pointer in it
Component * comp = getComponent("positionComponent");
mComponents.remove(comp);

For some reason, it calls the destructor of the comp pointer but doesn't delete it; items that are removed through destructor gets removed, while all the other items in the list kept intact. What can cause this behavior?

Gasim
  • 7,615
  • 14
  • 64
  • 131
  • The destructor of a pointer does nothing... – aschepler Nov 27 '13 at 00:45
  • Remove does not delete items from list: http://stackoverflow.com/questions/799314/difference-between-erase-and-remove – VladimirM Nov 27 '13 at 00:45
  • not sure what you mean when you say it calls the destructor but doesn't delete it... does it call `Component::~Component()`, but doesn't free the memory? This code shouldn't be calling `Component::~Component()`, as it's not destroying a `Component`, just a `Component*`. – filipe Nov 27 '13 at 00:45
  • 3
    @VladimirM `std::list::remove` *does* remove an element; I think you're referring to `std::remove` the general iterator algorithm. – WhozCraig Nov 27 '13 at 00:52
  • I think this was the weirdest thing I have seen in programming. I think XCode is having issues since I have been using it non stop all day. – Gasim Nov 27 '13 at 00:57

1 Answers1

6

Calling list.remove does call the destructor of the contained type, but in your case, the destructor for Component * is being called, which is a no-op. You must manually find the item and delete it before removing it.

auto item = std::find(mComponents.begin(), mComponents.end(), comp);
if(item != mComponents.end()) {
  delete *item;
  mComponents.remove(item);
}

This is the reason why it is not advisable to stick raw pointers in standard containers. You should use std::list<std::unique_ptr<Component>> instead. The unique_ptr will call delete on the managed object for you.

Or if you're using a pre-C++11 compiler, boost::ptr_list is another option.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • Even though the question I asked and didn't make sense at all (why would a pointer call destructor). I am guessing it was a memory leak that was giving unexpected behavior. I have been considering using smart pointers. I just needed to make the code work before I get into adding this amazing feature. – Gasim Nov 27 '13 at 01:00
  • 1
    @Gasim: If you need to delete the item every time it is removed from the list, clearly the list *owns* the item. Why don't just `std::list`? Why storing pointers? – Siyuan Ren Nov 27 '13 at 01:24
  • Do you mean `delete *item;`? – ildjarn Nov 27 '13 at 01:39