C++ Memory management for vector of Objects - c++

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).

Related

Does delete delete every element in a vector and free the memory?

vector<int>* v = new vector<int>;
for (int i = 0; i < 100; i++) {
(*v).push_back(i);
}
delete v;
Do I delete every element of the vector and free the memory? If not how do I free the memory?
An allocating new expression allocates memory, constructs a dynamic object into that memory, and returns a pointer to that object. When you pass such pointer to delete, the pointed object is destroyed and the memory is deallocated.
When an instance of a class, such as a vector is destroyed, its destructor is called. The destructor of vector destroys all elements of the vector.
Sidenote 1: It's rarely useful to use allocating new and delete. When you need dynamic storage, prefer to use RAII constructs such as containers and smart pointers instead.
Sidenote 2: You should avoid unnecessary use of dynamic memory in general. It's quite rare to need singular dynamic vector such as in your example. I recommend following instead:
std::vector<int> v(100);
std::ranges::iota(v, 0);
Sidenote 3: Avoid using (*v).push_back. It's hard to read. Prefer using the indirecting member access operator aka the arrow operator instead: v->push_back

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.

Vector of ints on heap and freeing memory

I'm creating a vector of ints on the heap like this:
std::vector<int> vec = *new std::vector<int>();
then I get to the end of my program and I need to free the memory, but using vec.clear() doesn't free the memory.
How do I do this properly?
Thanks and all the best
-Mitchell
How do I do this properly?
Replace this:
std::vector<int> vec = *new std::vector<int>();
With this:
std::vector<int> vec;
Problem solved.
Unlike other languages you may have come across, new is best avoided in most situations. It dynamically allocates objects, like in other languages. But unlike other languages, C++ doesn't have a garbage collector, so you need to manually destroy objects that you dynamically allocate. However, the way you've written your code, you've made that impossible.
You're dynamically allocating an object with new, which returns a pointer to the object. Then you are dereferencing that pointer (via *), and copying the object to vec. vec gets properly destroyed, but the dynamically allocated object that it was copied from does not. And since you didn't store that pointer, you're left with no way to access that object, and no way to dispose of it. In order to destroy that object, you would have had to capture the pointer, like this:
std::vector<int>* vec_pointer = new std::vector<int>();
Then later, you could call delete on the pointer, which destroys the object and deallocates the memory:
delete vec_pointer;
Thankfully, dynamic allocation is not a necessity as it often is in those other languages. Declaring an object creates it, and it is destroyed when it goes out of scope. So the simple line of code I showed you is sufficient, with no delete statement necessary.
As a side note, if you've determined, for some reason, that you must have dynamic allocation. Use a smart pointer (google that).
Your program is leaking memory.
std::vector<int> vec declares a vector on the stack. You create a second (empty) vector on the heap, and use it to copy-construct the one on the stack. Since it's empty, this effectively does nothing.
But, you've lost the pointer to the vector that was created on the heap (because you never stored it). So you can't delete it, and that memory can't be reclaimed. The vector on the stack, however, cleans up after itself just fine.
What you probably want is just:
std::vector<int> vec; // Vector on stack, no manual memory management required
If you really want to use the heap for some reason (the stack is faster, and vector object itself is of a small fixed size regardless of how many elements you put in it, so you don't have to worry about overflowing the stack), you can do:
// Declare pointer to vector, and initialize it with a new vector on the heap
std::vector<int>* vec = new std::vector<int>();
Or even (in C++11):
auto vec = new std::vector<int>();
Then, when you are done with it:
delete vec;

std::vector Destruction and Unexpected Memory Leak

Consider the following example:
#include <vector>
class Foo {
std::vector<int*> v;
public:
Foo() {
this->v.push_back(new int(23));
this->v.push_back(new int(24));
this->v.push_back(new int(25));
}
~Foo() {
}
};
int main() {
Foo f;
return 0;
}
When f goes out of scope in main(), f's destructor is called, which should indirectly free f.v. According to this, the destructor of each element of the vector v should now be called.
However, when I run this program in valgrind, I find that the int*'s were not deallocated.
$ valgrind --leak-check=full ./a.out
What am I missing here?
std::vector<T> does indeed call the destructor of T when it is destroyed. Here T is int *. The destructor of int * does nothing. The storage for the int * itself is freed, but the ints they point to are not.
Consider:
int main() {
int *x = new int(23);
return 0;
}
This exhibits the same problem; when x goes out of scope, its destructor is indeed called, and the storage for the pointer that is x is freed, but since the destructor of a pointer is a no-op, the pointed-to int is not freed.
More to the point, vector doesn't know how the ints were allocated. They might be allocated by new int, but they could also point to elements inside an array allocated with new int[200], or they might point to malloc'd data, or they might point into a mmap'd buffer, or they might point to struct elements, or two vectors might be pointing to the same ints... etc. vector isn't smart enough to divine what you want done with these, and so it leaves them alone (additionally, giving vector logic to delete pointed-to elements would break vectors of non-pointer elements such as std::vector<int>, as you can't delete an int!)
You need to either use a std::vector<int>, or use a smart pointer in conjunction with it, eg std::vector<boost::shared_ptr<int> >. Note that using smart pointers may add overhead; with C++0x you should be able to use std::vector<std::unique_ptr<int>> in conjunction with std::move to avoid this overhead. Boost also has pointer vectors that free the pointed-to elements as you expected as well.
The destructor of each element of the vector v should now be called
Yes: the int* objects stored in the vector are destroyed (which is effectively a no-op). The objects pointed to by the pointers in the container are not destroyed.
Consider the following, equally valid program:
{
int x;
std::vector<int*> v;
v.push_back(&x);
} // x cannot be delete'd because it isn't dynamically allocated.
You should use a smart pointer, like std::unique_ptr or shared_ptr so that you don't have to worry about the memory management (do not use std::auto_ptr; it is incompatible with the Standard Library containers because it isn't really copyable). If you don't use a smart pointer then you need to destroy the dynamically objects yourself; doing this correctly is rather difficult.
Each element of your vector is an int *. When an int * is destroyed, the language does not automatically call delete on it. In other words, it's the pointer being destroyed, not the pointee.
Since you are using the new keyword, the integers are being allocated on the heap rather than the stack. In other words, they are being allocated dynamically. In other words, you need to clean up after it.
The "destructor" for a pointer type is to simply delete that pointer. It does not touch the data which is located at the memory address stored by the pointer. Consider the following example:
int a = 5;
int* i = &a;
if (true)
{
int* j = i;
} //j goes out of scope, should *i and a be deleted? no.
So you will need to do this in the destructor:
std::vector<int*>::iterator iter;
for (iter = v.begin(); iter != v.end(); iter++)
{
delete *iter;
}

C++ Memory allocation question involving vectors

vector< int > vect;
int *int_ptr = new int(10);
vect.push_back( *int_ptr );
I under stand that every "new" needs to be followed by a "delete" at some point but does the clear() method clean this memory?
What about this method of doing the same thing:
vector< int > vect;
int int_var = 10;
vect.push_back( int_var );
From what I understand, clear() calls the variables destructors, but both vect.push_back() methods in this example push an object on the vector, not a pointer. so does the first example using an int pointer need something other than clear() to clean up memory?
The first method leaks because the vector never takes ownership of the allocated pointer. In fact, it doesn't contain a pointer at all, only a copy of the value.
The second method does not leak, as no memory is dynamically allocated (except internally in the vector -- it will handle that memory itself).
When you push_back on a vector, you add a copy of the data to the vector. Therefore, in both cases, the original data still needs to be freed. In the first case, you need to delete it; in the second, it will be "freed" by the stack pointer as it goes out of scope.
Vectors make copies on push_back. Since a pointer is 'just another variable' (but one that happens to point to memory), when you push_back an integer pointer that has been previously allocated, you copy the pointer's value into the vector, causing a potential dangling pointer, since there will be two pointers pointing at the same spot in memory.
In your first example, you would need to delete the memory manually. One strategy I've used in the past for meddling with graph classes is to have something like this (vast amounts of stuff redacted due to being at work and typing quickly):
class graph //quick-format
{
vector<node*> nodes;
add_node(node n)
{
node *temp = new node;
*temp = n;
nodes.push_back(temp)
}
~graph()
{
for(int i = 0; i < nodes.size(); i++)
delete nodes[i];
}
};
As a caveat, graph's copy semantics will have to be examined. As it stands, it will result in deleting previously-free'd memory. The advantage is that you can always have the same set of nodes hanging around. Caveat Emptor, like any direct memory usage..
However, if you simply push a non-pointer variable, there is no possibility of memory leaking from your end. Possibly the vector will leak, but... that is practically impossible at this point in the maturity of the tools.