0

I've created a list of stacks.

using namespace std;
list<stack<int>> stacks;
stack<int> *st = new stack<int>();      //LINE0
stacks.push_back(*st);
st->push(10);   
stack<int> *last = &stacks.back();
stacks.pop_back();    //LINE1
delete last;          //LINE2

LINE2 will cause an unhandled exception. Will LINE1 automatically deallocate the memory allocated at LINE0? Is LINE2 not necessary?

John
  • 193
  • 2
  • 14
  • 1
    `list> stacks = new list>();` - that is not how you create a list of stacks in C++. You don't need `new` unless you need a pointer to a thing rather than just the thing itself. If you want a list of stacks, that's just `list> stacks;`. – user2357112 May 14 '14 at 19:19
  • 3
    There's no reason to use `new` in this code. C++ is not Java, Stop using `new`. The line `stacks.push_back(*st);` dereferences a pointer and stores a __copy__ of that object into `stacks`, `st` now points to a different object. The `delete last;` tries to delete an object that wasn't created using `new`. You need to [read a good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and stop using `new`. – Blastfurnace May 14 '14 at 19:51

2 Answers2

1

To answer your question, stacks contains objects, not pointers, and none of them were created by you using new. So the line delete last; is an error because you are giving it an address that wasn't received from new.

The key here is that stacks.push_back(*st); stores in the list a copy of the object pointed to by st.

On the other hand, st does contain a pointer received from a new expression. You should do a delete st; otherwise you will leak that memory.

Manual resource management can be error prone and difficult to reason about so I suggest you simply stop using new unless and until it's really necessary.

Blastfurnace
  • 18,411
  • 56
  • 55
  • 70
0

Yes, containers delete stored object automatically.

C++ containers store exactly the type of data which is set as parameter. In this case list stores stack<int>, not pointer or reference to it. It means that container creates copy of object when push_back is running.

If you want store pointers in container, you should inform compiler about it:

list<stack<int>*>

That list won't delete stacks. It will delete pointers only.

By the way, I don't recommend to abuse allocating memory dynamically. It often leads to memory leaks.

Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65
  • If I use list*>, will the list delete the pointer itself? I do not need to delete the pointer? For example: list*> stacks; stack *st = new stack(); //LINE0 stacks.push_back(st); st->push(10); stack *last = stacks.back(); stacks.pop_back(); //LINE1 delete last; //LINE2. Do I need to use "delete last" to release the memory? – John May 14 '14 at 21:25
  • @John: You need to pause for a moment and understand what `stacks.push_back(*st);` is doing. Oh, and stop using `new` (so you won't need to use `delete` in the first place). – Blastfurnace May 14 '14 at 21:30
  • If I declare `stack *st = new stack();`, and `stacks.push_back(st);`, do I need to `delete st;`? or will `stacks.pop_back();` release the memory automatically? – John May 14 '14 at 23:01
  • @John: That won't compile because `stacks` holds objects and you can't push_back a pointer instead. Simply declare it as `stack st;` and it will be automatically destroyed when it goes out of scope. No `new` or `delete` required. The elements in `stacks` will also be automatically cleaned up when you do `pop_back()`. – Blastfurnace May 14 '14 at 23:09
  • @Blastfurnace: Forgot to mention that I will define `list*> stacks;`. Then do `stack *st = new stack();`, and `stacks.push_back(st);`. – John May 14 '14 at 23:17
  • @John Yes, you need to delete object which you created by `new` but you didn't do that. At the moment you delete copy of this object which is created by the list in method `push_back`. After that `pop_back` is trying to delete this object again, and it is the cause of the error. – Piotr Siupa May 14 '14 at 23:21
  • 1
    @John: Eeek, you might want to update this question or post a new one with your __actual code__. This has changed too much from what was originally posted. – Blastfurnace May 14 '14 at 23:29
  • +1, this answer is correct. I'm not sure why there is a down-vote, but it could be confusion between "deleting" something, and calling `delete` on a pointer to delete something else. – juanchopanza May 15 '14 at 06:13