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.
Related
If I use this line
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
If I create MyObject's in the stack and add them to the vector, they remain in the stack, right ?
MyObject obj1;
vec->push_back(obj1);
So if it go to the stack, than MyObject's added to the vector will be gone after method ends ? What will I have inside the vector than? Garbage?
Should I use this instead ?:
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
And if so, what about objects and primitives inside each MyObject ?
Should they also be dynamically created ?
Thank You
The std:vector as any other Standard Library container copies elements into itself, so it owns them. Thus, if you have a dynamically allocated std::vector the elements that you .push_back() will be copied into the memory managed by the std::vector, thus they will be copied onto the heap.
As a side note, in some cases std::vector may move elements if it is safe to do so, but the effect is the same - in the end, all the elements are under std::vector's jurisdiction.
A std::vector<MyObject> looks something like this (in reality it's much more complex):
struct Vector {
MyObject* data;
int size;
}
As you can see, the data is not directly inside the vector object. The vector always allocates the memory for the data on the heap. Here's what happens when:
you call .push_back: The vector copies the object into its own data block (which is on the heap and owned by the vector)
you copy the vector: The copied vector allocates new memory and copies all data from the existing vector into it
As you can see, the vector owns his data. That means, if you push_back a object into it, it doesn't matter where it came from because it gets copied.
If you have a std::vector<MyObject>* you have a pointer to a vector. This vector also owns his data, but you only have a pointer to it. That means, you have to delete it exactly once, otherwise you'll get a memory leak or a crash. Passing around pointers to a vector is OK, but need one class or function that "owns" it. This class/function has to guarantee that the vector still exists when the pointer to it is used.
The third case is a std::vector<MyObject*>. As every vector, this one also owns his data. But this time, the data is only a pointer. So the vector only owns the pointer, but not the objects to which the pointers are pointing. If you do something like this:
std::vector<MyObject*> getObjects() {
MyObject obj1("foo");
MyObject obj2("bar");
std::vector<MyObject*> vec;
vec.push_back(&obj1);
vec.push_back(&obj2);
return vec;
}
The returned vector only contains garbage because you only saved the address to a object on the stack to it. These objects are destroyed when the function returns, but the pointers in the vector are still pointing to that memory block on the stack.
Additionally, keep in mind that this
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
Doesn't store heap allocated objects to the vector. It just stores pointers of type MyObject. If you want to do something like that remember to create the objects first, before you use them. You can do that with something like the following:
for (int i = 0; i < vec->size(); i++) {
vec->at(i) = new MyObject();
}
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.
I have a few questions/examples about how memory management works for Vectors.
vector<int> vec1(10);
vector<int> vec2(10);
vec1 = vec2;
In a case like this, vec1's old memory is unreachable now. Is it still a memory leak here or would vec2's old memory realize there nothing referencing it and get cleaned up?
In another example
struct foo
{
vector<int> foo_vec(50);
int* arr;
}
void myFunction()
{
vector<foo> vec(10);
vec[0].arr = new int[50];
vec.erase(vec.begin());
}
Since I used erase() on the first vector element which contained arr with the allocated memory, does erase() release that memory or do I need to release it manually prior to the erase? Also when vec goes out of scope, are all the foo_vec vectors in vec automatically cleaned up? Thanks for any help.
In the case of
vector<int> vec1(10);
vector<int> vec2(10);
vec1 = vec2;
the previous contents of vec1 are erased since int is just a POD. If the vector consisted of pointers to objects instead of ints and these were allocated with new you would have to delete what those pointers point to before you assign, otherwise you would end up with memory leaks which your second example shows:
vector<foo> vec(10);
vec[0].arr = new int[50];
vec.erase(vec.begin()); // this will *not* call delete on vec[0].arr
Normally what you do to make things simpler for yourself is to use smart pointers like unique pointers (or e.g. boost::shared_array/scoped_array). When the vector goes out of scope or you erase the vector the delete (or delete []) will be automatically called.
struct foo
{
std::vector<int> foo_vec(50);
std::unique_ptr<int[]> arr;
}
...
vec[0].arr.reset(new int[50]);
vec[0].arr[12] = 42;
...
vec.erase(vec.begin()); // this will call delete[] on vec[0].arr
Does erase() release that memory or do I need to release it manually prior to the erase?
The rule: Always use delete for each new. vector ain't no magic - it doesn't know how you obtained that pointer, so it won't delete it, you need to do it.
Also when vec goes out of scope, are all the foo_vec vectors in vec automatically cleaned up?
Yes, their destructor is called and they're deallocated. However, you will leak memory if the destructor doesn't delete[] arr;.
By the way, a piece of good advice: your code violates encapsulation. You should allocate (new) and free (delete[]) the memory pointed to by foo::arr in the destructor and the constructor (foo::foo() and foo::~foo()), respectively.
Finally, the obligatory question: why foo::arr isn't a vector<int> itself?
Of course it will be cleaned.
No, if destructor of foo doesn't do this (or if you don't do it manually before erase).
Hello I have this question:
I would like to have a vector as class member. This is perhaps my question
easier for you and I apologize for that.
how should I declare the vector? And is this correct? std::vector<int> *myVector; or std::vector<int> myVector ?
how should I handle this vector in dealloc?
How can I initialize the array into a if?
Is this correct?
if(myCondition)
{
if(!myVector) //is this correct?
myVector = new std::vector<int>(); //is this correct? on this i have a error
}
You most certainly want to use std::vector<int> myVector. No need to initialize it, as it gets automatically initialized in the constructor of your class and deallocated when your class is destroyed.
Just use automatic allocation: declare it as a member like this:
class YourClass
{
std::vector<int> myVector;
// ...
};
The array gets constructed automatically before any of your constructor is run and is destroyed automatically when your object is deallocated, you don't need to care about it (also, the default copy constructor and assignment operator will handle copying gracefully automatically).
If, instead, you want to create the array only after a particular condition, you have to resort to a (smart) pointer and dynamic allocation, but IMHO it's quite cumbersome (especially because you then have to get right the "big three" - copy constructor, assignment operator, destructor); you could instead simply allocate the vector with automatic allocation and use a separate flag to mark your array as not initialized, or just check if its size is 0.
That depends entirely on context - what the vector means and why you need it. Should it be shared among multiple objects? If you don't know, don't keep a pointer, go with your second option.
std::vector<int> myVector;
If you have strong reasons to have a pointer, then please use a smart pointer, the one that provides most appropriate ownership for your situation - shared_ptr, scoped_ptr, unique_ptr or whatever_ptr
Most of the time, when we use standard library, We do not need to care about the memory allocation/deallocation. The template will handle it automatically. eg. The memory of a std::vector will be increase or decrease according to the elements stored in this vector. This would be an example.
Therefore, almost you can use it this way in your case.
std::vector<int> myVector //your second declaration
if(myCondition)
{
myVector.push(some_int); // use it directly
}
The memory the vector used will be deallocated when the Class object you created is destroyed.
If I create a vector of vector of vector, if I clear the first vector, or the first vector gets deleted, will all the child vectors call the destructor and free the memory or will it cause a memory leak? Thanks
If you have:
vector <vector <vector <int> > > > v;
v.clear();
then destructors will be called suitably for all the subvectors.
There will only be a memory leak if you used new to create the contained vectors. Calling clear() on a vector will NOT call delete on the contained items.
The STL offers only value-semantics. This means that you shouldn't bother with memory allocation/deallocation issues as long as you don't put pointers into your containers. Objects are destructed when deleted from the container, so also when the container itself is destructed (or cleared).
This also means that many operations on those containers will involve (default) constucting, copying, and destructing objects.
Yes. Destructor will be called and the memory will be freed.