0

Suppose I have a struct:

struct Foo {
  std::set<int> nodes;
};
Foo foo;

After inserting some elements into nodes of foo, I want to release the memory that nodes holds, and I get some inspirations from Is std::vector memory freed upon a clear?

Can

 std::set<int>().swap(foo.nodes)

release the memory properly?

My question differs from how to free memory from a set. Since the int is the built-in type, we cannot delete it as a pointer, which is considered in how to free memory from a set.

By the way, clear() shall not release the memory.

Community
  • 1
  • 1
chenzhongpu
  • 6,193
  • 8
  • 41
  • 79
  • 3
    Possible duplicate of [how to free memory from a set](http://stackoverflow.com/questions/3779138/how-to-free-memory-from-a-set) – Dutow Jul 21 '16 at 13:15
  • @Dutow `set` is not a set of pointers, we cannot delete it as http://stackoverflow.com/questions/3779138/how-to-free-memory-from-a-set does. – chenzhongpu Jul 21 '16 at 13:23
  • 2
    `std::vector` is completely different container, why do you assume that `std::ser` has the same behavior? – Slava Jul 21 '16 at 13:24
  • @chenzhongpu To me the question is whether you have determined through testing that the memory _needs_ to be released - i.e. whether it isn't released (A) right away or (B) later when required by other allocations. If either of these are true, then there isn't an issue. – underscore_d Jul 21 '16 at 14:05

1 Answers1

2

foo.nodes.clear(); will clear the set. But note that the C++ runtime may not release the memory immediately back to the operating system, so the effect on memory consumption might be difficult to measure.

std::set<int>().swap(foo.nodes); will achieve a similar result, but it does suffer from the overhead of an anonymous temporary being created.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 3
    @chenzhongpu who told you that? – Slava Jul 21 '16 at 13:25
  • 1
    @Bathsheba I'd also add that the memory is automatically released upon set destruction. I'm not sure if it's obvious for the OP. – HolyBlackCat Jul 21 '16 at 13:26
  • 1
    ^ There's definitely a missing `set` there. @chenzhongpu `clear()` _need not **immediately**_ release the memory. But it's available if anything else needs it more later... surely? – underscore_d Jul 21 '16 at 13:29
  • @underscore_d: good point: I've put that in. You'd indeed *hope* that the memory would become available if something else needed it. – Bathsheba Jul 21 '16 at 13:34
  • @batsheba: clear() only guarantees that the set does not contain elements anymore, i.e. `size()=0`. Some container actually implementations do retain memory. That's the reason for the `std::set().swap(nodes)` idiom. So if OP really cares about memory being released, I'd advise the latter. – peterchen Jul 21 '16 at 13:37
  • 1
    @peterchen that idiom is for `std::vector` which is known to keep memory indeed. That's why new method `std::vector::shrink_to_fit` added in C++11. Did you think why such method was not added to `std::set`? – Slava Jul 21 '16 at 13:41
  • 1
    It's much harder for `std::set` *not* to give it's memory back to the runtime library. `std::vector` more than likely would retain the data buffer it's already acquired, as an optimisation strategy. – Bathsheba Jul 21 '16 at 13:45
  • Yeah, it's evident why `vector` would benefit from keeping memory around despite deleting its elements, as you might want to re-fill it to the same capacity. But for non-contiguous containers, where - I presume? - it's a lot more likely that every insertion requires a new allocation, one might assume by symmetry that such containers are much more eager to release their previously allocated memory. – underscore_d Jul 21 '16 at 13:58
  • @Slava: fair point. However, as long as std::set::clear does not *guarantee* releasing memory (which I've never seen mentioned, which isn't much), an implementation would be allowed to keep a pool of preallocated nodes around. – peterchen Jul 21 '16 at 14:47
  • @Slava: it's common practice for vectors to overallocate, *and* explicitely exposed by vector.reserve. that seems to me sufficient reason to provide a `shrink_to_fit()` independent of the question whether `clear()`releases memory. – peterchen Jul 21 '16 at 14:49
  • @peterchen problem is that `std::set::swap()` does not guarantee releasing memory either. – Slava Jul 21 '16 at 14:55
  • @Slava: I was under the impresison that containers will release memory they own (back to the heap) when destroyed. But yeah, you are right, that's just a convenient assumption - by the same raitonale std::set might cache preallocated nodes globally, rather than per instance. – peterchen Jul 21 '16 at 15:52
  • @peterchen std::set does not even have to cache globally, it does not have to exchange that pool when swapped. – Slava Jul 21 '16 at 16:06