+ 2

shrink_to_fit on cleared vector

Hi I believe shrink_to_fit is not needed once we have done clear on vector... Right? Once we clear, all objects are destroyed and do we need to call shrink_to_fit even after vector.clear()?

26th Sep 2022, 7:00 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
10 odpowiedzi
+ 3
Vectors have a size and a capacity. The vector will reserve more space than it needs, so it doesn't have to reallocate every time you do a push_back. vector.clear() will set the size to 0 but leave the capacity unchanged. So the vector still takes up the same amount of space even if the contents are gone. Which might be a problem or it might not be. shrink_to_fit will* resize the vector so it gives up some space. (*according to cppreference, it "might" give up space, and it's implementation dependent.)
26th Sep 2022, 9:11 PM
Schindlabua
Schindlabua - avatar
+ 3
Hm. So when vector says it has capacity 6, internally it has an array that has a length of 6. Not all of this space is occupied by objects. When the vector says it has size 4, then 4 elements in this length 6 array are occupied with objects. calling .clear will delete all the objects, but the vector internally still has an array of size 6. So, after a clear, no space has been reclaimed (unless your vector elements allocated additional space), but the elements have been destroyed. Calling shrink_to_fit will resize this internal array, so that's when space is reclaimed. No destructors are called though because the objects are already gone and you are reclaiming "unused" memory. Does that make sense? Maybe read up about the "placement new" operator, it's what the vector class uses behind the scenes.
30th Sep 2022, 9:19 AM
Schindlabua
Schindlabua - avatar
+ 2
Ketan Lalcheta hm, after you print "added" you call .clear, which makes it so 4 destructors are running, no? Not sure I understand where your confusion is coming from! The objects are destructed during the clear. The shrink_to_fit doesn't do any destroying.
27th Sep 2022, 4:31 PM
Schindlabua
Schindlabua - avatar
+ 1
Thanks Schindlabua More confusion now as below code nieither after shrink fit nor after scope ends of v calls destructor Why no destructor at the end is called as v is already out of scope before done is printed https://code.sololearn.com/ciSSePEePBpc/?ref=app
27th Sep 2022, 7:21 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
I am reiterating your last sentence that is "The objects are destructed during the clear. The shrink_to_fit doesn't do any destroying." If objects are destryoed by clear, what shrink to fit has to do ? My origin ques is related to this only... why both needed at same time back to back. If clear gives us memory back to reuse by destroying, whats the need of shrink to fit .... I have idea that clear just reduces the size , but not capacity .... i just need to analyse or observe that some memory should be released post we call shrink to fit ...isnt it ? If no, then lets only stick to clear and dont neee to go with immediate call of shrink to fit
30th Sep 2022, 4:22 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
Thanks .. I am able to follow what you are trying to say, but still could not visualize the difference in terms of cout statements I have tried in below code: https://www.sololearn.com/compiler-playground/cWCdQfzoRERd As objects are already destroyed, what else is still there with vector? I have added global allocation and deallocation cout statements for new and delete. Why heap memory is released after both operations i.e. clear and shrink to fit? I am literally getting confused now as It should have only called delete post shrink to fit, not the clear...Right?
2nd Oct 2022, 10:48 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
shrink_to_fit causes a reallocation (so, deallocation followed by allocation). Let me jot down the general idea: int size; int capacity; T* data; void push_back(T& thing) { if (size >= capacity) { capacity *= 2; data = realloc(data, capacity); } data[size++] = thing; } void clear () { std::destroy(data, data + size); size = 0; } void shrink_to_fit() { realloc(data, size); capacity = size; } Obviously theres many issues with this code but I hope this somewhat explains it. `clear` destroys objects, shrink_to_fit resizes the internal array which also causes some memory operations. Note how in the clear function, the `data` array does not change size, meaning the vector still uses the same amount of memory. Only the elements within the array are destroyed. When a destructor runs, it doesn't necessarily mean that heap space is being reclaimed. :)
2nd Oct 2022, 9:10 PM
Schindlabua
Schindlabua - avatar
+ 1
Thanks a lot Schindlabua One more doubt Objects are created on heap or stack ? I mean class object to be inserted into vector...... if those are on heap, what else destructor cant do to release memory ? If on stack, what is expected additionally from heap ? Again thanks for your help to make me clear my doubts for better understanding of mine
3rd Oct 2022, 8:33 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
It's a pleasure ;) The vector's internal array is allocated on the heap, so the elements live on the heap too. Keep in mind that the `delete` (and `new` too) operator does two things: 1. call the destructor 2. free memory The destructor itself does not do any freeing. You can even call destructors yourself: Foo foo; foo.~Foo(); Constructors and destructors are normal functions like any other. So if we really want to, we can allocate some space first, and call the constructor some time later (using "placement new"). This is more or less what the `new` operator does: // allocate memory Foo* foo = (Foo*)malloc(sizeof(Foo)); // construct object at memory location `foo` new (foo) Foo(); And then do the same in reverse, to implement our own `delete`: // destruct object foo->~Foo(); // free memory free(foo); The vector class does the constructing and destructing manually. The memory is already allocated, since the vector class keeps an array internally where the objects go into.
3rd Oct 2022, 6:03 PM
Schindlabua
Schindlabua - avatar
+ 1
Sounds good.... amazing Just to re iterate my understanding: Clear destroys the objects and it is not releasing back the memory Shrink to fit does release the memory which is extra than current size We do observe destructor call and memory release differently due to mechanism of vector in terms of placement new... why placement new, beacuse it does not have to allocate wirh each push_back Thanks a lot for clarifying the doubts.... I was doing this wrong all the time as i left everything to compiler post .clear() with a mis conception that memory is released back by just doing clear
4th Oct 2022, 4:20 AM
Ketan Lalcheta
Ketan Lalcheta - avatar