This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Elements retained even after using delete[]
(2 answers)
Closed 4 years ago.
I created a Vector class containing an array (stored in a heap) and an integer n_rows counting the amount of elements inside the array. In order to delete the array properly during the instance destruction I used the delete as explained here.
Class (in header file):
private:
int n_rows;
int* vect;
public:
Vector(int);
~Vector();
std::string toString(); // returns elements from vect
Destructor (in .cpp):
Vector::~Vector(){
delete [] this->vect;
cout << this->toString() << endl;
}
However if I print the array vect after deleting it, seemingly just the first two entries get deleted.
Example:
// Vector:
[2 2 2 2 2 2]
// Destruction
[0 0 2 2 2 2]
My questions:
Is this resource properly deleted?
Why does it just appear that the two first elements get modified?
Your destructor free the memory pointed to by vect, but it doesn't do anything to the contents of that memory.
Dereferencing an invalid pointer (like the one you have after doing delete[] on it) leads to undefined behavior. Just don't do it.
The memory is freed up when you delete it, but it's not necessarily overwritten/set to zero or anything like that. Accessing the freed memory is undefined behavior and anything might happen, but what often happens (and happened in this case) is that you get the old values that were there before it was deleted. In other words, when it is deleted, it is mostly just "marked for being available again".
The program usually won't waste time writing over the deleted memory. If the memory is reassigned, then whatever is getting the memory will most likely initialize it however it wants anyway.
Related
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.
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.
This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 5 years ago.
I made a dynamic array (example):
int *a;
a = new int[3];
a[0] = 10; a[1] = 20; a[2] = 30;
Than I create a vector which stores pointers:
vector<int*> pa;
pa.push_back(&a[0]);
After I deleted (freed) the memory with "delete[] a;", I can still access to the element, that I push_backed. (cout << *pa[0]; output: 10)
Why is this happen? When I "delete[] a", it only deletes the pointer to the elements, but the elements are still accessable?
Your statement about how delete[] works is backwards. It deletes the elements but not the pointer. Continuing to use the pointer after its contents have been deleted, as you're doing, is undefined behavior. This means that literally anything is allowed to happen if you do it, so you shouldn't do it. It's by pure luck that you can still access the elements now, and bad things will happen in the future if you do it.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How does delete[] know it's an array? (C++)
How does delete[] “know” the size of the operand array?
suppose we have the following class
class Data
{
public:
Data() : i(new int) { *i = 0; }
~Data() { delete i; }
private:
int *i;
};
now we create array of 100 elements of type Data
Data* dataArray = new Data[100];
we know that operator new will call Data constructor for the 100 objects because it knows how many objects created, Now let's delete this array, if we say delete dataArray the destructor for first object only will be called even we know that the memory for the 100 objects we be released - will cause memory leak - and that because they allocated as one block, but if we say delete[] dataArray the destructor for the 100 objects will be called, but this is a dynmaic memory and i didn't specify how many object in there and as i know there is no overhead with the array to know how many objects in it, so how the runtime environment knows the number of objects to destruct before it free that memory?
First, delete dataArray is illegal. It might destroy the first object. It might do nothing. It might crash. It might summon demons through your nose. Don't do it.
As for how delete [] determines how many elements to store, it depends on the C++ library implementation. Typically there's an element count right before the first element (this may be part of the metadata that's always associated with dynamic allocations, or it might be extra data added for delete []); the delete [] implementation will look at this count to determine how many times to call the destructor; it will then adjust the pointer to point before the element count before actually freeing the memory (this is one reason why delete dataArray can break badly).
It depends on what the compiler does, but basically 2 options :
Store data just before the actual objects (array size, allocated size), a la malloc.
Keep a global map of pointers associated with an array size.
That's why you need to use either operator delete or the operator delete[] in each particular case. They are not interchangeable and they do different things. The implementation keeps some compiler/library-specific bookkeeping information about each memory block that these operators use.