How to clear vector in C++ from memory [duplicate] - c++

This question already has answers here:
C++ delete vector, objects, free memory
(7 answers)
Closed 7 years ago.
I'm new to C++ so this may be a newbie question however I'm not entirely clear how to clear it from memory. I've searched online and looked are several answers but was unclear on how to properly execute what im trying to do.
How can i clear my vector from memory correctly in c++? Thanks and i apologize if this is a dup post.
vector<ElementData> Elements;
As mentioned by a comment below, i would like to return the memory used as well.
except that it will not return any memory to the system as the
capacity remains unchanged.

If you want to reset you vector back to a empty state then we can use the swap trick to swap the contents of the vector into a temporary that will get destroyed and free the memory
vector<ElementData> Elements
// fill the vector up
vector<ElementData>().swap(Elements);
This will create a temporary empty vector, swap it with the one you have so now it is empty and then destroy everything in the temporary vector.
You can see it working in this little example
int main() {
std::vector<int> foo(500);
std::cout << foo.capacity() << std::endl;
std::vector<int>().swap(foo);
std::cout << foo.capacity() << std::endl;
}
Live Example

std::vector variables are normally destructed automatically when you go out of scope, or when the class object they are members of are destroyed. The destructor of std::vector also destroys all elements in the vector.
To completely clear a vector explicitly, first clear the vector (destroy the elements)
v.clear()
then return the memory previously reserved for the vector elements
v.shrink_to_fit();
http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
Only call shrink_to_fit if it's likely that the vector previously contained far more elements than you are going to fill it with.

When your program ends, vector's dtor will get called and delete your vector for you, since you've allocated it on the stack. Furthermore, the dtor for ElementData will get called for each one in the vector.

In most cases, the best way is to limit the scope of the vector to where it's actually needed. So, instead of something like:
vector<Elements> Elements;
... do some work with Elements ...
Elements.clear(); // or whatever "trick" you want to use
... do more work where Elements is not needed ...
You would do this:
{ // begin a new scope
vector<Elements> Elements;
... do some work with Elements ...
} // Elements is now out of scope, its memory has been freed
... do more work where Elements is not needed ...
The other benefit of this is that after Elements has gone out of scope, you can't accidentally reuse it. If the function is small, you probably don't need to create a new explicit scope. Returning from the function will have the same effect.

You don't have to do anything special. Since both the vector and the elements inside are statically allocated (i.e. not created by new), when the vector gets out of scope, it's deallocated and the destructor gets called on all ElementData inside. If you would have vector<ElementData*>, where the vector only contains pointers to ElementData, then you would also have to delete all the ElementData yourself.

Elements.clear() will do what you want.
Here are the rest of the functions available to vectors.

Related

How does vector not destroy element twice after reducing its size?

For testing purposes, I was trying to create my own vector class, and I couldn't figure out how std::vector size reduction works.
class A
{
A()
{ std::cout << "A constructed") << std::endl; }
~A()
{ std::cout << "A destroyed") << std::endl; }
}
main()
{
std::vector<A> vec(3, A());
vec.resize(2);
std::cout << "vector resized" << std::endl;
}
Output is
A constructed (1)
A constructed (2)
A constructed (3)
A destroyed (1)
Vector resized
A destroyed (2)
A destroyed (3)
When vec.resize(2) is called, the third element is destroyed, but the vector's capacity is still 3. Then when vec is destroyed, all of its elements including the one already destroyed should be destroyed. How does std::vector know that he has already destroyed that element? How can I implement that in my vector class?
There's a difference between capacity and size. Given a std::vector<T> v; The vector has allocated memory for v.capacity() elements. But only in the first v.size() places contain constructed T objects.
So, v.reserve(1000) on an empty vector won't call any additional constructors. vec.resize(2) in your example destroys the last element and vec[2] is now an empty place in memory, but memory still owned by the vec.
I think your allocation looks like buffer = new T[newSize];. That is not how std::vector works which would not allow Ts that do not have default constructors. Maybe you did not realize this, but whenever you obtain a piece of memory, it already contains objects, let it be T x; or even new double[newSize]; which returns an array of doubles (although their constructors are empty).
There is only one way to get usable uninitialized memory in C++, which is to allocate chars. This is due to the strict aliasing rule. There also (is|must be) a way how to call a constructor explicitly on this memory i.e. how to create an object there. The vector uses something called placement new which does precisely that. The allocation is then simply buffer = new char[newSize*sizeof(T)]; which creates no objects whatsoever.
The lifetime of the objects is managed by this placement new operator and explicit calls to destructors.
emplace_back(arg1,arg2) could be implemented as {new(buffer + size) T(arg1,arg2);++size;}. Note that simply doing buffer[size]=T(arg1,arg2); is incorrect and UB. operator= expects that the left size(*this) already exists.
If you want to destroy an object with e.g. pop_back, you must do
buffer[size].~T();--size;. This is one of the very few places where you should call the destructor explicitly.
The simple answer is that vector internally manages constructor and destructor calls, often by using inplace operator new and operator delete methods.
Having popped an element, it is immediately descructed, and while the memory is still available, and may still contain some remnant values, std::vector itself knows which elements still need to be deleted, and won't call the destructor again.
When vec.resize(2) is called, the third element is destroyed, but the vector's capacity is still 3.
Yes. The capacity is how many elements the vector's internal array can physically hold. The size is how many elements in that array are actually valid. Shrinking the size does not affect the capacity at all.
Then when vec is destroyed, all of its elements including the one already destroyed should be destroyed.
The 3rd element that was previously destroyed and removed from the array is not destroyed again. Only size number of elements are destroyed, not capacity number of elements, like you are thinking.
How does std::vector know that he has already destroyed that element?
It tracks the size and capacity separately. When an element is removed from the array, the elements that follow it are moved down the array by 1 slot each, and the size is decremented.

Do I need to call clear() when I am done with a vector? [duplicate]

This question already has answers here:
Should I always call vector clear() at the end of the function?
(5 answers)
Closed 4 years ago.
All of the questions that I have seen ask about managing memory when the elements of the vector are dynamically allocated/are pointers. My question is just about a vector that has been allocated on the stack, with a simple type, for example, int.
If I have the following code:
std::vector<int> vec(5);
for(int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
Do I need to call clear() when I am done?
No.
Classes in C++ have a destructor that gets called when the class object goes out of scope or is deleted. While you are correct that std::vector dynamically allocates space under the hood, the std::vector destructor will deallocate the memory for you resulting in a happy leak-free program.
From the cppreference page, when the vector destructor is called it...
Destructs the container. The destructors of the elements are called and the used storage is deallocated. Note, that if the elements are pointers, the pointed-to objects are not destroyed.
Also note that from the cppreference on clear, the function...
Leaves the capacity() of the vector unchanged...
So when you call clear the memory isn't even actually being free'd! (see this SO question for more on what clear is actually doing)
If you are worried about freeing the memory allocated (and hence blocked for use elsewhere) in a (large) vector, you should
make sure the scope/lifetime of the respective vector is limited to the region/time of its imminent use, so that its destruction automatically frees the memory.
failing that (for whatever reason), you may
vec.clear(); // reduces the size to 0, but not the capacity
vec.shrink_to_fit(); // suggests to reduce the capacity to size
assert(vec.capacity()==0);
Note that vector::clear() de-allocates no memory in vector (only memory, if any, dynamically allocated by the vector elements). vector::shrink_to_fit() suggests the reduction of the memory footprint of vector to its actual size, but the implementation can chose to ignore that request.
Finally, an alternative to clear() followed by shrink_to_fit() is the swap idiom (which also works prior to C++11):
vector<Tp>().swap(vec);
assert(vec.capacity()==0);
What happens here is that a new empty vector (of the same type) is constructed and then immediately swapped with vec, so that vec becomes empty (with zero size and capacity). Finally, because the new vector is a temporary (un-named) object, it is destructed, whereby de-allocating the memory originally kept with vec.

C++ vector and struct free [duplicate]

This question already has answers here:
C++ Correct way to free a vector of a custom class
(3 answers)
Closed 5 years ago.
I've been working on an implementation of the n-bodies problem, and I have to make a struct (asteroid) and a vector which contains those structs.
My question is, if I create the vector like this:
vector<asteroid> b(n_asteroids + n_planets);
And then I fill it like this:
for (it = 0; it < n_asteroids + n_planets; ++it){
b[it] = {arg1, arg2, arg3...}
}
Do I need to call delete for either the asteroid structs or the vector? Or will the destructor free them when my program ends main?
Thanks!
You don't need to delete your vector, as you didn't use new to allocate it. Regarding vector members, from http://www.cplusplus.com/reference/vector/vector/~vector/
This calls allocator_traits::destroy on each of the contained elements, and deallocates all the storage capacity allocated by the vector using its allocator.
So the answer is no for you case.
But note that if you hold pointers in your vector, e.g. vector<asteroid *>, which you allocated with new, and you don't have any reference left to this pointer, you will need to manually delete it.
Your vector has an automatic storage class which means the memory it occupies will be released when it will go out of scope. This means that the contents of the vector will be released too.
If the vector held pointers that pointed to dynamically then you would have the need in delete.

do I have to clear std::vector before deleting it

So far I have always been using vector::clear() before deleting the vector. But is it necessary? Isn't the vector::clear() function called in destructor anyway?
// Consider I have this vector
std::vector<uint32_t>* myVector = new std::vector<uint32_t>(50);
... // vector gets filled
myVector->clear(); // <-- redundant??
delete myVector;
myVector = nullptr;
No, all elements of the std::vector are destructed upon std::vector destruction anyway so using clear is redundant. You can see the documentation for std::vector::~vector here.
Additionally, dynamically allocating the vector as you have done in the question is typically unnecessary - just initialise via
std::vector<uint32_t> myVector;
//...
then myVector and all it's elements will be destructed when it goes out of scope.
No, there is no need to call clear manually. It may or may not get called internally when the vector is destroyed, but any objects in the vector will get destroyed one way or the other as the vector is destroyed.

C++ delete vector, objects, free memory

I am totally confused with regards to deleting things in C++. If I declare an array of objects and if I use the clear() member function. Can I be sure that the memory was released?
For example :
tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);
Can I safely call clear to free up all the memory? Or do I need to iterate through to delete one by one?
tempVector.clear();
If this scenario is changed to a pointer of objects, will the answer be the same as above?
vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
You can call clear, and that will destroy all the objects, but that will not free the memory. Looping through the individual elements will not help either (what action would you even propose to take on the objects?) What you can do is this:
vector<tempObject>().swap(tempVector);
That will create an empty vector with no memory allocated and swap it with tempVector, effectively deallocating the memory.
C++11 also has the function shrink_to_fit, which you could call after the call to clear(), and it would theoretically shrink the capacity to fit the size (which is now 0). This is however, a non-binding request, and your implementation is free to ignore it.
There are two separate things here:
object lifetime
storage duration
For example:
{
vector<MyObject> v;
// do some stuff, push some objects onto v
v.clear(); // 1
// maybe do some more stuff
} // 2
At 1, you clear v: this destroys all the objects it was storing. Each gets its destructor called, if your wrote one, and anything owned by that MyObject is now released.
However, vector v has the right to keep the raw storage around in case you want it later.
If you decide to push some more things into it between 1 and 2, this saves time as it can reuse the old memory.
At 2, the vector v goes out of scope: any objects you pushed into it since 1 will be destroyed (as if you'd explicitly called clear again), but now the underlying storage is also released (v won't be around to reuse it any more).
If I change the example so v becomes a pointer to a dynamically-allocated vector, you need to explicitly delete it, as the pointer going out of scope at 2 doesn't do that for you. It's better to use something like std::unique_ptr in that case, but if you don't and v is leaked, the storage it allocated will be leaked as well. As above, you need to make sure v is deleted, and calling clear isn't sufficient.
vector::clear() does not free memory allocated by the vector to store objects; it calls destructors for the objects it holds.
For example, if the vector uses an array as a backing store and currently contains 10 elements, then calling clear() will call the destructor of each object in the array, but the backing array will not be deallocated, so there is still sizeof(T) * 10 bytes allocated to the vector (at least). size() will be 0, but size() returns the number of elements in the vector, not necessarily the size of the backing store.
As for your second question, anything you allocate with new you must deallocate with delete. You typically do not maintain a pointer to a vector for this reason. There is rarely (if ever) a good reason to do this and you prevent the vector from being cleaned up when it leaves scope. However, calling clear() will still act the same way regardless of how it was allocated.
if I use the clear() member function. Can I be sure that the memory was released?
No, the clear() member function destroys every object contained in the vector, but it leaves the capacity of the vector unchanged. It affects the vector's size, but not the capacity.
If you want to change the capacity of a vector, you can use the clear-and-minimize idiom, i.e., create a (temporary) empty vector and then swap both vectors.
You can easily see how each approach affects capacity. Consider the following function template that calls the clear() member function on the passed vector:
template<typename T>
auto clear(std::vector<T>& vec) {
vec.clear();
return vec.capacity();
}
Now, consider the function template empty_swap() that swaps the passed vector with an empty one:
template<typename T>
auto empty_swap(std::vector<T>& vec) {
std::vector<T>().swap(vec);
return vec.capacity();
}
Both function templates return the capacity of the vector at the moment of returning, then:
std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';
outputs:
1000
0
Move semantics allows for a straightforward way to release memory, by simply applying the assignment (=) operator from an empty rvalue:
std::vector<int> vec(100, 0);
std::cout << vec.capacity(); // 100
vec = vector<int>(); // Same as "vector<int>().swap(vec)";
std::cout << vec.capacity(); // 0
It is as much efficient as the "swap()"-based method described in other answers (indeed, both are conceptually doing the same thing). When it comes to readability, however, the assignment version makes a better job.
You can free memory used by vector by this way:
//Removes all elements in vector
v.clear()
//Frees the memory which is not used by the vector
v.shrink_to_fit();
If you need to use the vector over and over again and your current code declares it repeatedly within your loop or on every function call, it is likely that you will run out of memory. I suggest that you declare it outside, pass them as pointers in your functions and use:
my_arr.resize()
This way, you keep using the same memory sequence for your vectors instead of requesting for new sequences every time.
Hope this helped.
Note: resizing it to different sizes may add random values. Pass an integer such as 0 to initialise them, if required.