So I have a vector of vectors that is heap allocated:
std::vector<std::vector<int>>* matrix = new std::vector<std::vector<int>>();
After putting a considerable amount of data into matrix. What is the correct way to delete this object?
Does delete matrix deallocate all of the internal vectors?
Yes delete matrix; will be fine.
You may want to consider if you need to dynamically allocate your vector. Vectors always store their data on the free-store (heap) so they don't need to be dynamically allocated for that reason. They have a very small stack foot-print.
If you must allocate your vector dynamically then you should seriously consider using a smart pointer such as a std::unique_ptr or a std::shared_ptr, then you won't need to call delete at all:
auto matrix = std::make_unique<std::vector<std::vector<int>>>();
Yes, it does. delete matrix calls the destructor of the std::vector<std::vector<int>> before returning memory. The destructor call will call the destructor of all its elements, std::vector<int>.
Also, most usage of std::vector wouldn't require you to create it on the heap. I suspect the same with your case.
Related
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
I have come against a problem with my pointer vectors...
And i got an idea what the problem might be:
When I create a pointer to a vector, the pointer reserves the size of the vector on the heap. So that basicly means, that the pointer now points to the memory of the vector without anything inside... When i now resize or pushback the vector, will the pointer now still point to the whole memory of the vector or just the memory which has been allocated at the beginning?
I also want to know, if there are some tricks you can do to fix that (if what i think is true). Is the "vector.reserve(n)" a method of accomplishing this? Or is there something i could do to overwrite the pointers memory adress, to a vector after it has been initialised?
"When I create a pointer to a vector, the pointer reserves the size of the vector on the heap.
No, it doesn't! When you create a pointer to a vector, you have a pointer. Nothing more. It doesn't point to anything yet, and it certainly hasn't reserved any "heap memory" for you.
You still need to actually create the vector that will be pointed-to.
std::vector<int>* ptr1; // just a pointer;
ptr1 = new std::vector<int>(); // there we go;
delete ptr1; // don't forget this;
auto ptr2 = std::make_shared<std::vector<int>>(); // alternatively...
Y'know, it's very rare that you need to dynamically-allocate a container. Usually you just want to construct it in the usual fashion:
std::vector<int> v;
That's it. No need for pointers.
When i now resize or pushback the vector, will the pointer now still point to the whole memory of the vector or just the memory which has been allocated at the beginning?
Regardless of how you constructed/allocated it, the vector itself never moves spontaneously (only the dynamic memory that it is managing for you internally), so you do not need to worry about this.
I also want to know, if there are some tricks you can do to fix that
No need, as there's nothing to fix.
Is the "vector.reserve(n)" a method of accomplishing this?
Theoretically, if this were a problem (which it isn't) then, yes, this could possibly form the basis of a solution.
Vector is class that has internal pointer to vector's elements using continuous block of memory in the heap. Long enough for all reserved vector's elements (capacity() method)
So, if you create vector (in local scope's stack OR in the heap - doesn't matter) it creates this layout
[ vector [ ptr-to-data ] ] --> HEAP: [ 1 ][ 2 ][ 3 ]
vector<int> v1(3); // whole vector instance in the stack
vector<int> *pv2 = new vector<int>(3); // pointer to vector in the heap
each of these 2 vector instances has its pointer to its elements in the heap as well
Vector manages its pointer to the data internally.
When you push_back() more elements than its current .capacty() it will re-allocate new continuous block of memory and copy-construct or move all old elements to this new block.
Is there a way to move a unique_ptr
unique_ptr<int[]> foo;
into a vector?
vector<int> bar;
No, you cannot just hand vector a piece of memory and expect it to use that as its array storage. A vector's storage must come from the allocator that the vector uses.
You could try to use allocator gimmicks to pawn the memory off to the vector in some way. But even that would be tricky, as the vector can allocate as many ints as it wants, regardless of what size you tell it.
You can move the contents of a unique_ptr into an element of the array. Say, if you had a vector<unique_ptr<int[]>>. But you can't just slap a piece of memory into a vector.
How to allocate memory to Vector dynamically ?
vector<Point> vInPts; // My Input Vector - i have dumped some value ( of size 6 )
// Doing Some calculation on the input vector points
vector<Point> vOutPts; // How to dynamically allocate memory for this output vector Points
Chances are you do not need to allocate the vector itself dynamically. Internally, the vector will allocate the memory it needs to store its elements dynamically, and will take care of managing this memory. So just declare the vector in automatic storage:
vector<Point> vOutPts;
You can allocate a predetermined amount of memory for the vector by calling std::vector::reserve.
If you absolutely must allocate the vector dynamically, make sure you know all about memory management, and read up on smart pointers and RAII.
If you know the size you want, then you can allocate and initialise enough elements with:
vOutPts.resize(size);
or you can create it with that size:
vector<Point> vOutPts(size);
Otherwise, you can grow the vector one element at a time:
vOutPts.push_back(some_point);
If you know (roughly) how many elements you want to push, then you could make that a bit more efficient by allocating some memory beforehand, without initialising any elements:
vOutPts.reserve(approx_size);
This way
vector <Point> *myvect= new vector<Point>()
But don't forget to call:
delete myvect
when you're done using it or else you'll create a leak.
Please notice that allocating the vector itself this way won't be the same as allocating dinamically the vector contents. This dynamic allocation of the vector itself should be done only if for example you intend to create a vector inside a function and return it by reference. Automatic memory management is easier to handle, less error prone and above all safer than dynamically allocating objects... and therefore whenever you don't have to you should avoid this dynamic allocation
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;