Assume we want to declare a function in C++, in which I declare a local variable int p=new int [10]; and I do some operations afterwards and in the end I return p; .
As is often said, if we use new , we must delete. But I think in this case, we should NOT delete, right? Otherwise, it can't return p at all, right? However, I am also thinking if we should delete the item the function returns when we test it in int main().
The rule is that for every new there must be a delete (and for every new[] a delete[] *), but it need not be in the same scope. It is common to have functions dynamically create an object and transfer ownership of that object to the caller. The caller will then be responsible for deleting the memory.
That being said, you should avoid directly calling new and delete in your code, and prefer using other constructs that are safe (take care of the memory automatically for you). In the particular case you mention, a std::vector<int> initialized with 10 elements will have little overhead over the pointer and will ensure that the memory is released whenever the object is destroyed.
* Depending on your implementation, there might be cases where you new (or new[]) and not delete, if the memory is handed to a smart pointer. For example in C++11 you could do:
std::unique_ptr<int[]> f() {
std::unique_ptr<int[]> p(new int[10]); // new is unmatched
// ...
return p;
}
This is fine, as handling the pointer to the std::unique_ptr ensures that it will call delete[] internally when it goes out of scope (if not moved to a different smart pointer).
The caller would need to know you returned something created with new [], and call delete [] when necessary. There is a lot of scope for error in such a construct. Better return something that takes care of its own memory, such as an std::vector or an std::unique_ptr.
delete should be done when the program is done using the array. It doesn't have to be in the same function.
If delete always needed to be done when the function ends, it would get added automatically (unique_ptr is a way to tell C++11 to automatically free something new when the function ends)
They are allocated from heap. So you can and should delete on anywhere outside the function.
New and Delete does not use stack. Same for malloc and free.
You can delete [] p in the new scope it is returned after you are done with it. However, it is not a good practice to just allocate a memory with new and giving the ownership to another scope. You can utilize std::vector or smart pointers.
Related
I am new to c++ but from what I understood you need to delete objects from memory when you are done with them.
Having a class called myClass. If I create a new instance and call some of its functionalities. Like so:
MyClass p;
p.funcCall(12);
p.anOtherFuncCall(4);
How am I supposed to free the memory occupied by p again? I read this Microsoft article. But if I change it to:
MyClass* p = new MyClass
... call fucntions
delete p;
I can no longer call my functions like p.funcCall(12).
If I understood memory management in c++ incorrectly I would love to hear that as well.
In this code
MyClass p;
p.funcCall(12);
p.anOtherFuncCall(4);
You don't have to manually delete p. It is automatically invalidated once it goes out of scope. This is explained in greater detail here. You can just leave it this way.
MyClass* p = new MyClass
... call fucntions
delete p;
You can also do it that way if you want. Since p is not a MyClass anymore but a pointer to one, the syntax is different, though. You have to write it like this instead:
p->funcCall(12);
So basically C++ won't manage memory for you, at least it's not a default feature of the language. That certainly doesn't mean that you need to store every object as a pointer and free it manually though. In your case the object is initialized in the local scope which means it will get destroyed as soon as it leaves that scope. This is because you constructed it as a value, if you had allocated memory yourself for it (i.e global scope) then you're responsible for freeing said memory. There's another option for pointers as well though, using smart pointers will automate the cleanup of objects in the global scope.
I am new to C++ so I am struggling alot with memory management.
I know that when we have a pointer to an array, it means it is dynamically created, so I should delete it later in my destructor. But what if we have a normal array, do I need to include a delete statement in the destructor for this normal array too? or the program will do that automatically?
for example, I have a normal array like this
int myArray[];
and in my destructor, should I include this:
delete[] myArray;
?
Thanks in advance,
But what if we have a normal array, do I need to include a delete statement in the destructor for this normal array too? or the program will do that automatically? for example, I have a normal array like this int myArray[]; and in my destructor, should I include this: delete[] myArray; ?
No. If you don't new[] an array, then you don't need to delete[] it. Everything else is done automatically. This is why using std::array, std::vector etc. is so great: There is no need to write new[] when you use them, so you don't have to worry that you maybe forgot a delete[].
"I know that when we have a pointer to an array, it means it is dynamically created"
That is not correct. You can take a pointer to basically anything, including stack variables. Dynamic allocation generally gives you back a pointer (which is probably where the confusion stems from) but not every pointer comes from dynamic allocation. Consider this:
void foo()
{
int a;
int* b = &a; // No dynamic allocation.
}
Again, since there is no new here, there should be no delete.
I know that when we have a pointer to an array, it means it is dynamically created
No. That induction is not correct. A pointer can also point to non-dynamically created arrays.
so I should delete it later in my destructor.
If your class instance is responsible for destruction of that array then destructor is indeed one place where that should probably be done.
do I need to include a delete statement in the destructor for this normal array too? for example, I have a normal array like this int myArray[];
No. Only objects created with new are destyroyed with delete. And only objects created with new[] are destroyed with delete[]. Not anything else.
or the program will do that automatically?
Yes.
Objects with automatic storage duration are destroyed automatically at the end of the scope where they are declared. That is what the name of the storage class comes from. Objects with static storage duration are destroyed after main returns. Temporary objects are destroyed at the end of the full expression (unless their lifetime is extended by binding the object to a reference). Member variables are destroyed when the super (not meaning base class in this context) object is destroyed.
Only dynamically created objects must be destroyed manually.
While it is useful to learn how it is done, there is quite rarely need to do manual memory management in C++. The standard library provides containers that do the hard work for you. Instead of dynamically creating an array, one would typically use std::vector.
Memory management isn't easy for anyone, especially to those who are new to C++. I recommend looking into the terms stack and heap, which should hopefully clarify some things up.
I know that when we have a pointer to an array, it means it is dynamically created, so I should delete it later in my destructor.
This isn't exactly true, a pointer is just a variable that holds the address (where a variable lives) of something. You can make a pointer to any variable like this:
int a = 5;
int *aPtr = &a;
This doesn't mean that a or aPtr are dynamic.
However a pointer made like this would be dynamic and needs to be deleted:
int *aPtr = new int(5);
The biggest difference here is the new keyword. new makes dynamic memory (what is put onto the heap). Every time you use the new keyword, you should use the delete keyword to match with it.
But what if we have a normal array, do I need to include a delete statement in the destructor for this normal array too? or the program will do that automatically? for example, I have a normal array like this int myArray[]; and in my destructor, should I include this: delete[] myArray; ?
No, you wouldn't need to call delete[] myArray; because this array would be made on the stack. What I mean by that is that when you return out of the function that made this array, the array would be cleaned out of memory.
An alternative to manually managing memory is to use the std::array, std::vector, or even smart pointers such as std::unique_ptr or std::shared_ptr that clean themselves up after the reference to it is gone.
I hope this helps!
What I got from the answers is that I don't need to delete anything if new is not triggered. Same goes to delete[] and new[] . Normally created arrays like the one in my question int myArray[] is not dynamically created, so it does not need to be dynamically deleted in destructor, meaning, the compiler will do the deleting part for me. Thanks all
Suppose that you have the following function:
void doSomething(){
int *data = new int[100];
}
Why will this produce a memory leak? Since I can not access this variable outside the function, why doesn't the compiler call delete by itself every time a call to this function ends?
Why will this produce a memory leak?
Because you're responsible for deleting anything you create with new.
Why doesn't the compiler call delete by itself every time a call to this function ends?
Often, the compiler can't tell whether or not you still have a pointer to the allocated object. For example:
void doSomething(){
int *data = new int[100];
doSomethingElse(data);
}
Does doSomethingElse just use the pointer during the function call (in which case we still want to delete the array here)? Does it store a copy of the pointer for use later (in which case we don't want to delete it yet)? The compiler has no way of knowing; it's up to you to tell it. Rather than making a complicated, error-prone rule (like "you must delete it unless you can figure out that the compiler must know that there are no other references to it"), the rule is kept simple: you must delete it.
Luckily, we can do better than juggling a raw pointer and trying to delete it at the right time. The principle of RAII allows objects to take ownership of allocated resources, and automatically release them when their destructor is called as they go out of scope. Containers allow dynamic objects to be maintained within a single scope, and copied if needed; smart pointers allow ownership to be moved or shared between scopes. In this case, a simple container will give us a dynamic array:
void doSomething(){
std::vector<int> data(100);
} // automatically deallocated
Of course, for a small fixed-size array like this, you might as well just make it automatic:
void doSomething(){
int data[100];
} // all automatic variables are deallocated
The whole point of dynamic allocation like this is that you manually control the lifetime of the allocated object. It is needed and appropriate a lot less often than many people seem to think. In fact, I cannot think of a valid use of new[].
It is indeed a good idea to let the compiler handle the lifetime of objects. This is called RAII. In this particular case, you should use std::vector<int> data(100). Now the memory gets freed automatically as soon as data goes out of scope in any way.
Actually you can access this variable outside of your doSomething() function, you just need to know address which this pointer holds.
In picture below, rectangle is one memory cell, on top of rectangle is memory cell address, inside of rectangle is memory cell value.
For example, in picture above, if you know that allocated array starts from address 0x200, then outside of your function you can do next:
int *data = (int *)0x200;
std::cout << data[0];
So compiler can't delete this memory for you, but please pay attention to compiler warning:
main.cpp: In function ‘void doSomething()’:
main.cpp:3:10: warning: unused variable ‘data’ [-Wunused-variable]
int *data = new int[100];
When you do new, OS allocates memory in RAM for you, so you need to make OS know, when you don't need this memory anymore, doing delete, so it's only you, who knows when execute delete, not a compiler.
This is memory allocated on the heap, and is therefore available outside the function to anything which has its address. The compiler can't be expected to know what you intend to do with heap-allocated memory, and it will not deduce at compile time the need to free the memory by (for example) tracking whether anything has an active reference to the memory. There is also no automatic run-time garbage collection as in Java. In C++ the responsibility is on the programmer to free all memory allocated on the heap.
See also: Why doesn't C++ have a garbage collector?
Here you have an int array dynamically allocated on the heap with a pointer data pointing to the first element of your array.
Since you explicitly allocated your array on the heap with new, this one will not be deleted from the memory when you go out of scope. When you go out of scope, your pointer will be deleted, and then you will not have access to the array -> Memory leak
Since I can not access this variable outside the function, why doesn't
the compiler call delete by itself every time a call to this function
ends?
Because you should not allocate memory on the heap that you wouldn't use anyway in the first place.
That's how C++ works.
EDIT:
also if compiler would delete the pointer after function returns then there would be way of returning a pointer from function.
I have a vector of pointers like this:
std::vector<foo*> stuff;
I initialize each element with a new foo();:
My question is what happens when I reassign one of the vector's elements, say
stuff[3] = new foo();
Am I leaking memory and should I have called delete[] before this? Is this a case where I should be using smart pointers? (never have so far)
Normally I would not be using new but I 'm learning Qt and this is how it seems done in the examples. Qt seems to have smart pointers of its own; should I be using one of those?
Thanks.
yes, you leak when stuff get destructed leaving all those dynamic allocated foo undeleted and unreachable unless you iterate through the vector and call delete.
typically when you want a vector of pointer you use std::shared_ptr
std::vector<std::shared_ptr<foo>> stuff;
stuff[3] = std::make_shared<foo>();
this could potentially be a performance bottleneck if the vector is huge and you try to copy it( then perhaps you want to wrap it in another shared_ptr ), but if you are only accessing the element of the vector it eliminate all the problems about who delete what and when that come with the raw pointer approach.
My question is what happens when I reassign one of the vector's elements, say
stuff[3] = new foo();
Am I leaking memory
Yes, you're leaking memory. The vector doesn't know who's responsible for owning the object you allocated. It's can't tell the difference between:
stuff[3] = new foo();
and
foo f;
stuff[3] = &f;
Therefore it will not any cleanup for you.
and should I have called delete[] before this?
Not quite. delete[] is used to destroy a dynamically allocated array; it's what you would use to destroy something allocated via new[]. To destroy something allocated via plain new, you should use plain delete.
Is this a case where I should be using smart pointers? (never have so far)
Yes. If you used std::shared_ptr<foo> (or boost::shared_ptr<foo> if you can't use C++11), then the std::shared_ptr object would take responsibility for deleteing the object for you.
I don't see any relation with Qt in your code. memory leak occurs when don't call delete after you allocated the object with new. what you should do it to run a loop on that vector and call delete on each item.
a vector makes a copy of the object and stores the copy. Now in your example, the vector is of the type foo*. So when it is passed a pointer to foo, vector makes a copy of the pointer, not the foo itself. Now when you reassign and do other stuff, the copy of the pointer is freed by vector, but not the memory pointed by the pointer. Imagine you have a vector of keys, so the vector makes a copy of key passed to it, and frees the copy of the key. But it never touches the lock for which the key is. That you need to handle yourself. You can get the value and free the element yourself before reassigning.
If foo are QObjects then assign to each a parent (which will be responsible for deleting them - although they could be deleted manually too). And in that case, do not use smart pointers as that will create ownership conflicts.
Let say I have a hypothetical pointer declared with new like so:
int* hypothetical_pointer = new int;
and create another hypothetical pointer, with the same value:
int* another_hypothetical_pointer = hypothetical_pointer;
If I were to go about deleting these, which were declared with new, would I have to delete both pointers, or only the one explicitly declared with new? Or could I delete either pointer?
delete destroys the dynamically allocated object pointed to by the pointer. It doesn't matter if there are one or 100 pointers pointing to that object, you can only destroy an object once.
After you delete hypothetical_pointer;, you cannot use hypothetical_pointer or another_hypothetical_pointer because neither of them points to a valid object.
If you need to have multiple pointers pointing to the same object, you should use a shared-ownership smart pointer, like shared_ptr, to ensure that the object is not destroyed prematurely and that it is destroyed exactly once. Manual resource management in C++ is fraught with peril and should be avoided.
There is only one block of memory from the single call to new, so you must delete it once and only once, when all users are done with it.
boost::shared_ptr is a nice way to accommodate multiple users of the same data - the last reference going out of scope triggers delete on the underlying memory block.
boost::shared_ptr<int> ptr1(new int);
boost::shared_ptr<int> ptr2(ptr1);
// memory deleted when last of ptr1/ptr2 goes out of scope
Only call delete on one of those pointers - doesn't matter which, since they both contain the same value, as a pointer. Do not use either pointer after calling delete.
Correct answer is that you don't delete either. You delete what they point at.
Now...if they both point at the same thing, how many times do you think you should delete what they point at?