C++ vector and struct free [duplicate] - c++

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.

Related

Constructor of objects in heap array [duplicate]

This question already has answers here:
Object array initialization without default constructor
(14 answers)
Closed 3 years ago.
So, I have an object with a constructor. This object doesn't support empty constructors because there are constants that must be assigned in the constructor. Something like this:
class Object {
public:
const int foo;
Object(int f) : foo(f) {
// other stuff
}
}
Now I have another function that keeps a dynamically allocated array of objects.
Object* objects;
I need to be able to allocate this memory using new[] and delete[] but also use the constructor. I can't seem to figure out how to do this.
Something like this would be ideal
objects = new Object[numObjects];
for (int i = 0; i < numObjects; ++i) {
object[i](foos[i]);
}
I could use malloc and free, then new the objects in place, but that would be non ideal as I would have to loop through the objects in the destructor and manually destruct them, then free the memory. Seems messy.
You could use list initialisation:
objects = new Object[3]{1, 2, 3};
But this only works with a constant size array.
I could use malloc and free, then new the objects in place
This is indeed exactly the way to create an array of dynamic length containing objects of a non-default-constructible type. Except instead of malloc, it would be more idiomatic to allocate an array of std::byte with new[]. This is also how to allocate an array of certain number of objects that you would like to create later.
But there's no need to write that yourself, since the standard library provides you with std::vector, which does this for you:
std::vector<Object> mycars(numObjects, Object(42));

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.

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

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.

Does std::vector<T>::clear() call destructor of the content? [duplicate]

This question already has answers here:
What do I need to do before deleting elements in a vector of pointers to dynamically allocated objects?
(5 answers)
Does std::vector call the destructor of pointers to objects? [duplicate]
(3 answers)
Closed 8 years ago.
If I have a std::vector of something (say,does std::vector::clear() call destructor of the content? For example, if I have a data as vector, is the following code valid?
char * pd;
for(vector<char *>::iterator it = data.begin(); it != data.end(); ++it) {
pd = *it;
delete pd;
}
Or, is it redundant as data.clear() would do that? I presume not, i.e. manual deallocation of the content is needed. I presume, data.clear() will not call implicit destructor for the contents? Is it correct? This is for pre C++11.
To answer your title: std::vector<T>::clear() does call the destructor for each element. However, for primitive datatypes like char* the destructor is trivial (standardese for "does nothing") which is practically the same as if no destructor is called.
Note: A destructor is not the same as the delete operator.
So what your question should be: "Does std::vector<T*>::clear() call delete on its elements?" and here the answer is: No, it does not call delete. You have to do it manually like shown in your example code, or you can (and probably should) use objects like std::string or smart pointers instead of raw pointers. Those do the memory management for you, and their destructors (which get called, see above) call the delete for you.
If your items are dynamically allocated and your vector contains pointers to them, you will have to manually call delete on each pointer in that container before calling clear(). Otherwise you have a memory leak.
If they are objects that are not dynamically allocated then you do not need to do anything - the destructor (if there is one) of the objects in the vector will be called when the vector is cleared.
std::vector clear() does call the destructor of each element in the vector:
http://www.cplusplus.com/reference/vector/vector/clear/
But in your case it won't delete the contents of your dinamically allocated memory. I suggest using string instead of char*

container out of scope and memory management [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does std::list::remove method call destructor of each removed element?
Assume I have this:
void f(...)
{
.
.
std::list<X*> xList;
.
// Then i fill the list
std::list<X*>::iterator iter;
for (iter = xList.begin(); iter != xList.end(); ++iter)
{
*iter = new X();
}
}
When xList goes out of scope, I know that the container should call the destructor of the objects that are contained within the list? First, is that true?
If so, then since the list contains pointers to class X shouldn't the destructor ofX be called when xList goes out of scope? Thus freeing any memory that was held by X?
Yes and no.
Each elements' destructor will be called.
However this won't result in the effect you want. The elements are of type X*, thus the destructor of X* will be called (which does nothing for pointer type) rather than destructor of X that you need. You need to explicitly delete your elements. In general, if you have new in your code, there should be a corresponding delete.
In C++ standard library design a container is the only owner of the contained elements so when the container is destroyed all elements are destroyed.
However note that "destroying" a naked pointer in C++ is a no-operation so the pointed-to element will not be deleted (a naked pointer may point to statically allocated data or to data that is owned by some other container).
What you can do is creating either an std::list of the elements (instead of pointer to the elements) or (in case you need a pointer because of, for example, polymorphism) you can instead use smart pointers that can take care of the pointed elements if you like so.