-2
struct node {
    std::vector<struct node*> * list;
}

int main() {
   struct node * n = new struct node;
   n->list = new std::vector<struct node*>();
   n->list->push_back(n);
   return 0;
}

How can I delete the n->list with freeing all the pointers that the list is storing?

Will it be n->list->clear()? Or do I have to traverse n->list and call delete or free operator on each element in the list.

Dr. Programmer
  • 75
  • 1
  • 1
  • 5

3 Answers3

3

std::vector does not assume ownership of dynamically created objects.
(Even if it wanted to, or you created a specialisation or your own implementation, it's impossible to distinguish dynamic allocations from other pointers.)
You need to traverse the vector and free the elements.

molbdnilo
  • 55,783
  • 3
  • 31
  • 71
3

The safer/simpler would be

struct node {
    std::vector<node> list;
};

int main() {
   node n;
   n.list.resize(1);
}

or if you need pointer:

struct node {
    std::vector<std::unique_ptr<node>> list;
};

int main() {
   node n;
   n.list.push_back(std::make_unique<node>());
}
Jarod42
  • 173,454
  • 13
  • 146
  • 250
  • In this case where does the node and the list stay? The stack or in memory? – Dr. Programmer Oct 28 '15 at 12:58
  • Maybe a `std::shared_ptr` is more fitting as a container of pointers implies that you want shared ownership of the elements. Otherwise, you could store by value and simply `std::move` the elements around, right? – Snps Oct 28 '15 at 13:01
  • @Dr.Programmer: stack is memory so the answer for your question is: yes, these objects stay in memory on stack. When `main` function leaves stack for it is cleared (and so are the objects) – Michał Walenciak Oct 28 '15 at 13:03
  • @Jarod42: as Dr. Programmer seems to be new to c++ I'd suggest not to show him smart ptrs until he understands raw pointers good enought. Smart pointers may encourage him to use them without thinking. – Michał Walenciak Oct 28 '15 at 13:08
  • @MichałWalenciak - We should rather not have shown him raw pointers, which he already seems to misuse. – Bo Persson Oct 28 '15 at 13:11
  • @BoPersson: In provided examples (by Jarod42) what is the difference between smart pointer version and no-pointer version? None. It may be a source of misconception like: "use smart pointers everywhere, it will solve all your problems`. When you program in c++ you should know what raw pointers are and how to use them. – Michał Walenciak Oct 28 '15 at 13:19
  • @MichałWalenciak: Smart pointers are mostly more complicated because they forbid some misuses. – Jarod42 Oct 28 '15 at 14:55
  • @Jarod42: I am not against smart pointers, I use them almost everywhere. But first of all, I know where to use pointer and where to create something on stack. Without this knowledge I could create everything on heap which is not elegant nor fast. – Michał Walenciak Oct 28 '15 at 15:15
0

First of all: you don't need so much pointers.

If you want it be be this way, you should delete it exactly the same way you have 'newed' it :).

In your example:

int main() {
   struct node * n = new struct node;
   n->list = new std::vector<struct node*>();
   n->list->push_back(n);
   delete n->list;             // here's the change
   delete n;                   // another required delete
   return 0;
}

But as I said, too much news. You can write your struct node as:

struct node {
    std::vector<struct node*>  list;
}

it will cause the list to be automatically deleted when node object is being deleted.

This line: struct node * n = new struct node; also can be converted into: node n;

Michał Walenciak
  • 3,867
  • 4
  • 29
  • 57
  • If I call delete n->list, will it free the pointers the list is storing? – Dr. Programmer Oct 28 '15 at 12:56
  • Generally speaking vector takes care of its content, and it deletes it on destruction. What you should be aware of is that when vector holds pointers it will delete them but not objects these pointers point to. So: `vector` will delete all stored `int`s but `vector` will only delete storage for pointers but `int`s they point to will still be alive. – Michał Walenciak Oct 28 '15 at 13:01
  • Thanks. So I would have to traverse the list and call free on each node pointer. – Dr. Programmer Oct 28 '15 at 13:03
  • @Dr.Programmer exactly. But using non-pointer structure is safer - Less risk of leaking memory on invalid pointers. – Michał Walenciak Oct 28 '15 at 13:04
  • But If I didn't store pointers to the node then it would be adding copies of the node in the list. – Dr. Programmer Oct 28 '15 at 13:06
  • @Dr.Programmer: it usually isn't big deal :) If there is a real problem then pointers may be solution. There are also more 'advanced` techniques like `emplace_push` or `move semantics` from c++11 but don't bother yourself about them now as they may look complex and may discourage you to c++. – Michał Walenciak Oct 28 '15 at 13:15