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;
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
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();
}
I know the difference for following cases:
case 1: int a[10];
for case 1, memory for array is allocated on stack.
case 2: int *a = new int[10];
for case 2, memory is allocated on heap and a pointer is returned.
But what is the difference between below two declarations,
as for vector memory is always allocated on heap
vector<int> v1;
vector<int> *v2 = new vector<int>();
The following two statements create a vector<> however there are several differences between the two.
vector<int> v1;
vector<int> *v2 = new vector<int>();
First of all the actual vector data storage is going to be allocated from the heap or whatever source the designated memory allocator uses (see Where does a std::vector allocate its memory?) and this is the same for both.
The two differences are (1) where the vector<> management data is stored and {2} the lifetime for the vector<> and its allocated memory.
In the first case the vector<> management data is stored on local memory, the stack, and when the vector<> variable goes out of scope, the destructor is called to eliminate the vector data storage space on the heap and the vector management space on the stack. In the first case when the vector<> variable goes out of scope, the vector<> memory is properly released.
In the second case both the vector<> storage data space and the vector<> management space is on the heap.
So when the pointer variable containing the address of the vector<> goes out of scope, the destructor for the vector<> itself is not called. The result is memory that is not recovered since the destructor that would clean up and release the allocated memory for both the data storage area of the vector<> and the management storage area is never called.
One possibility for the second case to ensure that the vector<> is cleaned up properly is to use a smart pointer which when it goes out of scope will also trigger the destructor for the thing pointed to.
In most cases the need for the second case, using new to create the vector<> is rare and the first case is not only the most common but also safer.
Only std::vector storage memory is allocated on the heap, the remainder (that is some pointer to the storage + some extra data members) could normally be located on the stack, however by writing new vector<int>() you force the entire thing on to the heap.
Usually there is no need to allocate vectors this way.
I was thinking about a this situation not for a real implementation but to understand better how pointers works.
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
Ok, I know that have no sense to copy v[i] inside an other pointer, but I was thinking: copy do a memory leak?
After the execution of doComplexThings(), copy will continue to exist and will occupy space in the heap?
After deleting all elements it will continue to exist and point to a deallocated memory?
So logically if I do this things with complex objects I'll keep occupy the memory with unreference object? Or copy is saved in the stack because I don't use new? And at the end of doComplexThings it will be deleted?
I'm a bit confused, thanks!
There is some confusion on the topic of pointers in the C++ community. While it is true that smart pointers have been added to the library to alleviate problems with dynamic memory allocation, raw pointers are not obsolete. In fact, whenever you want to inspect another object without owning it, you should use a reference or raw pointer, depending on which suits your needs. If the concept of ownership is unclear to you, think of an object as being owned by another object if the latter is responsible for cleaning up afterwards (deleting the former).
For example most uses of new and delete should be replaces with the following (omitting std for brevity):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
Notice how a function that takes a T* doesn't need a smart pointer if it doesn't keep a copy of the T* it is given, because it doesn't affect the lifetime of the object. The object is guaranteed to be alive past the return point of do_stuff_with_T() and its function signature signals that it doesn't own the object by taking a raw pointer.
On the other hand, if you need to pass the pointer to an object that is allowed to keep the pointer and reference it later, it is unclear when the object will need to be destroyed and most importantly by whom. This is solved via a shared pointer.
ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
So how does the above factor in to your code. First of all, if the vector is supposed to own (keep alive) the ints it points to, it needs to hold unique_ptr<int> or shared_ptr<int>. If it is just pointing to ints held by something else, and they are guaranteed to be alive until after the vector is destroyed, you are fine with int*. In this case, it should be evident that a delete is never necessary, because by definition your vector and the function working on the vector are not responsible for cleaning-up!
Finally, you can make your code more readable by changing the loop to this (C++11 which you've tagged in the post):
for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
Again this is only true if some other object holds the ints and releases them, or they are on the stack but guaranteed to be alive for the whole lifetime of vector<int*> that points to them.
No additional memory is allocated on the heap when you do this:
copy = v[i];
variable copy points to the same address as v[i], but no additional array is allocated, so there would be no memory leak.
A better way of dealing with the situation is to avoid raw pointers in favor of C++ smart pointers or containers:
std::vector<std::vector<int>> myVector;
Now you can remove the deletion loop, which is an incorrect way of doing it for arrays allocated with new int[length] - it should use delete[] instead:
delete[] myVector[i];
Basically you're illustrating the problem with C pointers which lead to the introduction of C++ unique and shared pointers. If you pass a vector of allocated pointers to an opaque member function, you've no way of knowing whether that function hangs onto them or not, so you don't know whether to delete the pointer. In fact in your example you don't seem to, "copy" goes out of scope.
The real answer is that you should only seldom use allocated pointers in C++ at all. The stl vector will serve as a safer, easier to use version of malloc / new. Then you should pass them about as const & to prevent functions from changing them. If you do need an allocated pointer, make one unique_ptr() and then you know that the unique_ptr() is the "owner" of the memory.
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.