Let's assume I have two classes named classA and classB. I create a pointer to classA, and then dynamically allocate a single object using the new operator as follows:
classA *ptrA = new classA
classA has a member of type pointer to classB, and in its default constructor it allocates an array of objects of type classB on the heap as follows:
memberOfA = new classB[10]
and to complicate things further, classB has a member variable of type int*, and in its default constructor it allcoates an array of integer on the heap as follows:
memberOfB = new int[100]
Now, if I call a delete on ptrA using delete ptrA, how will the compiler go about deallocating the memory allocated by memberOfA and memberOfB.
Now, if I call a delete on ptrA using delete ptrA, how will the compiler go about deallocating the memory allocated by memberOfA and memberOfB.
When you call delete ptrA, the compiler will call the destructor of classA. If that destructor doesn't delete [] memberOfA then you're leaking both memberOfA and consequently memberOfB.
If instead of manual memory management (new and delete) you used automatic memory management (SBRM/RAII), then you wouldn't have to write any destructors and the resources you allocated would be freed as expected, for example:
std::unique_ptr<classA> ptrA(new classA);
std::unique_ptr<classB[]> memberOfA(new classB[10]);
std::unique_ptr<int[]> memberOfB(new int[100]);
This is in fact the modern C++ way to do it. The code becomes simpler to understand as the ownership semantics of the pointers are written in their type and there are no destructors lying around. An even better way would be to use std::make_unique(...) in place of new but I left it out for simplicity.
memberOfA and memberOfB is only deallocated if you put a delete[] in the destrutors of classA and classB. So if you had written the destructor of classA so that it freed the memory pointed to by memberOfA like this:
classA::~classA() {
delete [] memberOfA;
}
In this case the destructor would free the array calling the destructors of the elements pointed by the entries in memberOfA. The same can be said for the destructor of classB:
classB::~classB() {
delete [] memberOfB;
}
Remember using new must be paired with a subsequent delete at some point, if not you are look at a leak. Perhaps you should consider one of the smart pointer classes: unique_ptr, and shared_ptr.
If your design allows for classA and classB to use a unique_ptr or shared_ptr to the array, much of the dangers of a leak would have been overcome:
std::unique_ptr<classB[]> memberOfA(new classB[10]);
If the order of the deletion is of interest to you then, invoking the delete ptrA will result in the destructor of classA being called, and if we assume that it is implemented as hinted above (using delete []) then the delete [] operator will call the destructors of all the members in decreasing address order, quote from the Standard, draft N3690, ยง 5.3.5 / 6:
If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted. In the case of an array, the elements will be destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see 12.6.2).
This will of course lead to the destructor of classB being called for each element, which will again utilize the delete [] memberOfB which will release the array pointing to the integers.
It will not ... you should do that by implementing the destructor! You can do that by using the delete [] operator.
classA::~classA() {
delete [] memberOfA;
}
and
classB::~classB() {
delete [] memberOfB;
}
and then you do delete ptrA the order of execution will be:
call classA::~classA()
call classB::~classB() on each of the elements of memberOfA
deallocate memory for the array of ints pointed by memberofB
deallocate memory for the array of memberofA
deallocate memory for classA
Deallocation of memory can actually happen at later stages in some cases.
Alternatively, if you don't really need to work with pointer use arrays or vectors to hold your elements.
class classB
{
...
std::array<int,100> memberOfB;
...
};
class classA
{
...
std::array<classB,10> memberOfA;
...
};
std::unique_ptr<A> ptrA(new classA)
Related
What is the difference between delete and delete[] operators in C++?
The delete operator deallocates memory and calls the destructor for a single object created with new.
The delete [] operator deallocates memory and calls destructors for an array of objects created with new [].
Using delete on a pointer returned by new [] or delete [] on a pointer returned by new results in undefined behavior.
The delete[] operator is used to delete arrays. The delete operator is used to delete non-array objects. It calls operator delete[] and operator delete function respectively to delete the memory that the array or non-array object occupied after (eventually) calling the destructors for the array's elements or the non-array object.
The following shows the relations:
typedef int array_type[1];
// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;
// create and destroy an int
int *b = new int;
delete b;
// create and destroy an int[1]
int *c = new int[1];
delete[] c;
// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;
For the new that creates an array (so, either the new type[] or new applied to an array type construct), the Standard looks for an operator new[] in the array's element type class or in the global scope, and passes the amount of memory requested. It may request more than N * sizeof(ElementType) if it wants (for instance to store the number of elements, so it later when deleting knows how many destructor calls to done). If the class declares an operator new[] that additional to the amount of memory accepts another size_t, that second parameter will receive the number of elements allocated - it may use this for any purpose it wants (debugging, etc...).
For the new that creates a non-array object, it will look for an operator new in the element's class or in the global scope. It passes the amount of memory requested (exactly sizeof(T) always).
For the delete[], it looks into the arrays' element class type and calls their destructors. The operator delete[] function used is the one in the element type's class, or if there is none then in the global scope.
For the delete, if the pointer passed is a base class of the actual object's type, the base class must have a virtual destructor (otherwise, behavior is undefined). If it is not a base class, then the destructor of that class is called, and an operator delete in that class or the global operator delete is used. If a base class was passed, then the actual object type's destructor is called, and the operator delete found in that class is used, or if there is none, a global operator delete is called. If the operator delete in the class has a second parameter of type size_t, it will receive the number of elements to deallocate.
This the basic usage of allocate/DE-allocate pattern in c++
malloc/free, new/delete, new[]/delete[]
We need to use them correspondingly. But I would like to add this particular understanding for the difference between delete and delete[]
1) delete is used to de-allocate memory allocated for single object
2) delete[] is used to de-allocate memory allocated for array of objects
class ABC{}
ABC *ptr = new ABC[100]
when we say new ABC[100], compiler can get the information about how many objects that needs to be allocated(here it is 100) and will call the constructor for each of the objects created
but correspondingly if we simply use delete ptr for this case, compiler will not know how many objects that ptr is pointing to and will end up calling of destructor and deleting memory for only 1 object(leaving the invocation of destructors and deallocation of remaining 99 objects). Hence there will be a memory leak.
so we need to use delete [] ptr in this case.
The operators delete and delete [] are used respectively to destroy the objects created with new and new[], returning to the allocated memory left available to the compiler's memory manager.
Objects created with new must necessarily be destroyed with delete, and that the arrays created with new[] should be deleted with delete[].
When I asked this question, my real question was, "is there a difference between the two? Doesn't the runtime have to keep information about the array size, and so will it not be able to tell which one we mean?" This question does not appear in "related questions", so just to help out those like me, here is the answer to that: "why do we even need the delete[] operator?"
C++ delete[] operator ensures that Destructor for all object allocated with new[] is called. The following example demonstrates the same. Also, delete[] must be preferred (if new[] used previously) when the class has a non-default destructor to release the acquired resources. Otherwise, it might result in memory leaks.
Common Code:-
#include <iostream>
using namespace std;
class memTest{
public:
static int num;
memTest(){
cout<<"Constructor from object " << num++ << endl;
}
~memTest(){
cout<<"Destructor from object " << --num << endl;
}
};
int memTest::num=0;
Example 1:- use of new[] and delete may result in undefined behavior.
int main() {
memTest* Test1=new memTest[3];
delete Test1; //<-----
return 0;
}
Output 1:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2 //<-----
Example 2: The correct behavior is using new[] and delete[].
int main() {
memTest* Test1=new memTest[3];
delete[] Test1; //<-----
return 0;
}
Output 2:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2
Destructor from object 1 //<-----
Destructor from object 0 //<-----
delete is used for one single pointer and delete[] is used for deleting an array through a pointer.
This might help you to understand better.
What is the difference between delete and delete[] operators in C++?
The delete operator deallocates memory and calls the destructor for a single object created with new.
The delete [] operator deallocates memory and calls destructors for an array of objects created with new [].
Using delete on a pointer returned by new [] or delete [] on a pointer returned by new results in undefined behavior.
The delete[] operator is used to delete arrays. The delete operator is used to delete non-array objects. It calls operator delete[] and operator delete function respectively to delete the memory that the array or non-array object occupied after (eventually) calling the destructors for the array's elements or the non-array object.
The following shows the relations:
typedef int array_type[1];
// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;
// create and destroy an int
int *b = new int;
delete b;
// create and destroy an int[1]
int *c = new int[1];
delete[] c;
// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;
For the new that creates an array (so, either the new type[] or new applied to an array type construct), the Standard looks for an operator new[] in the array's element type class or in the global scope, and passes the amount of memory requested. It may request more than N * sizeof(ElementType) if it wants (for instance to store the number of elements, so it later when deleting knows how many destructor calls to done). If the class declares an operator new[] that additional to the amount of memory accepts another size_t, that second parameter will receive the number of elements allocated - it may use this for any purpose it wants (debugging, etc...).
For the new that creates a non-array object, it will look for an operator new in the element's class or in the global scope. It passes the amount of memory requested (exactly sizeof(T) always).
For the delete[], it looks into the arrays' element class type and calls their destructors. The operator delete[] function used is the one in the element type's class, or if there is none then in the global scope.
For the delete, if the pointer passed is a base class of the actual object's type, the base class must have a virtual destructor (otherwise, behavior is undefined). If it is not a base class, then the destructor of that class is called, and an operator delete in that class or the global operator delete is used. If a base class was passed, then the actual object type's destructor is called, and the operator delete found in that class is used, or if there is none, a global operator delete is called. If the operator delete in the class has a second parameter of type size_t, it will receive the number of elements to deallocate.
This the basic usage of allocate/DE-allocate pattern in c++
malloc/free, new/delete, new[]/delete[]
We need to use them correspondingly. But I would like to add this particular understanding for the difference between delete and delete[]
1) delete is used to de-allocate memory allocated for single object
2) delete[] is used to de-allocate memory allocated for array of objects
class ABC{}
ABC *ptr = new ABC[100]
when we say new ABC[100], compiler can get the information about how many objects that needs to be allocated(here it is 100) and will call the constructor for each of the objects created
but correspondingly if we simply use delete ptr for this case, compiler will not know how many objects that ptr is pointing to and will end up calling of destructor and deleting memory for only 1 object(leaving the invocation of destructors and deallocation of remaining 99 objects). Hence there will be a memory leak.
so we need to use delete [] ptr in this case.
The operators delete and delete [] are used respectively to destroy the objects created with new and new[], returning to the allocated memory left available to the compiler's memory manager.
Objects created with new must necessarily be destroyed with delete, and that the arrays created with new[] should be deleted with delete[].
When I asked this question, my real question was, "is there a difference between the two? Doesn't the runtime have to keep information about the array size, and so will it not be able to tell which one we mean?" This question does not appear in "related questions", so just to help out those like me, here is the answer to that: "why do we even need the delete[] operator?"
C++ delete[] operator ensures that Destructor for all object allocated with new[] is called. The following example demonstrates the same. Also, delete[] must be preferred (if new[] used previously) when the class has a non-default destructor to release the acquired resources. Otherwise, it might result in memory leaks.
Common Code:-
#include <iostream>
using namespace std;
class memTest{
public:
static int num;
memTest(){
cout<<"Constructor from object " << num++ << endl;
}
~memTest(){
cout<<"Destructor from object " << --num << endl;
}
};
int memTest::num=0;
Example 1:- use of new[] and delete may result in undefined behavior.
int main() {
memTest* Test1=new memTest[3];
delete Test1; //<-----
return 0;
}
Output 1:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2 //<-----
Example 2: The correct behavior is using new[] and delete[].
int main() {
memTest* Test1=new memTest[3];
delete[] Test1; //<-----
return 0;
}
Output 2:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2
Destructor from object 1 //<-----
Destructor from object 0 //<-----
delete is used for one single pointer and delete[] is used for deleting an array through a pointer.
This might help you to understand better.
Let's say
class A {
A* array;
public:
A (){
array= new A [4];
}
~A (){
delete array;
}
}
How do we free an object if we create such an object on heap like
A* object_ptr =new A();
I'm a bit confused about freeing a pointer that points to an object containing another pointer.....
Calling
delete object_ptr;
after
A* object_ptr =new A();
will invoke the destructor of the A pointed to by object_ptr. That means, if you fix your wrong
~A (){
delete array;
}
to
~A (){
delete[] array;
}
your code will be fine and the internal pointer is freed correctly.
However, you really should use std::vector instead of new[]. It will make your life a whole lot easier. If you insist on new[], read about The Rule of Three.
Two things to note.
When deleting arrays you should use []. For example: delete [] array;
When deleting pointers the destructor of the allocated object will get called. You would call from your code: delete object_ptr; to delete your pointer.
Another important point to be aware of is what happens when you copy your object. If your object ever gets copies you will have problems where one destructor deletes the pointers out from under another object. This is why shared_ptr is a good alternative to raw pointers (see this question on how to use shared_ptr).
I have a C++ class, MyClass. It contains a constructor, destructor and an int pointer private: int *MyPtr;.
Somewhere, I allocate dynamically a MyClass Object:
MyClass *my = new MyClass(); //...
Then I call delete my;
Should MyClass have a destructor which uses something like delete MyPtr? Or is that MyPtr destroyed when I call delete my?
If you allocated MyPtr insid MyClass constructor then it's your responsibility to delete it. Otherwise if you delete an unallocated memory it causes undefined behavior.
An idiomatic way is to use smart pointer inside class if you need to dynamic allocate memory and delete it, smart pointer will look after memory deallocation for you.
probaby worth a read: rule of three
Or is that MyPtr destroyed when I call delete my?
No, when you call delete my; this will call the destructor of MyClass and unless you explicitly delete MyPtr in the destructor you will have a memory leak.
Should MyClass have a destructor which uses something like delete MyPtr?
Always delete dynamically allocated memory in your destructor - that is what destructors are meant for.
When you call
delete my
you don't deallocate the data of that class (unless you specify it in the destructor), so this will lead to a memory leak.
This is merely for curiosity sake because I have not used new and delete in c++ except for the most basic uses.
I know that delete releases memory. The thing I'm wondering is how does it handle more complex cases?
For instance, if I have a user-defined class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete [] intArray;
}
//public members here
private:
int* intArray;
};
Assuming the class allocates memory somehow for intArray, and then release it in the destructor, What if I used the class like this: MyClass* myClass = new MyClass(); and released it later with delete myclass;
How does delete handle the releasing of all the memory? Does the class destructor get called first to release all of the memory allocated by the class (ie int* intArray) and then release the memory allocated to hold the class?
What if I had a class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete anotherMyClass;
}
//public members here
private:
MyClass* anotherMyClass;
};
Assuming anotherMyClass is not allocated with the constructor, which would use up memory very quickly, what if there was a chain of MyClasses attached to each other like a linked-list? Would the delete statement in the destructor work in this case? Would each anotherMyClass be recursively released when the destructor gets called?
Are there any specific weird tricks or caveats with the new and delete statements that you know about?
Given a pointer (p) to a dynamically allocated object, delete does two things:
It calls the destructor of the dynamically allocated object. Note that when ~MyClass() completes, the destructors for any member variables of class type are called.
It frees the memory occupied by the dynamically allocated object.
It doesn't search the member variables of the object for other pointers to free; it doesn't free any other memory and doesn't do anything else.
If you need to free the memory pointed to by intArray, you need to delete it in the destructor of MyClass.
However, in almost all C++ code, you don't need to worry about this. You should be using smart pointers like shared_ptr, unique_ptr, auto_ptr, and scoped_ptr to automatically manage dynamically allocated objects. Manual resource management is difficult at best and should be avoided wherever possible.
This is part of a broader idiom, Scope-Bound Resource Management (SBRM, also called Resource Acquisition is Initialization, or RAII). This is by far the most important design pattern to understand and to use everywhere in your C++ code.
If in your class you had declared this instead:
boost::scoped_ptr<int> intArray;
then when the scoped_ptr<int> object is destroyed, it will free the pointer that it holds. You then do not have to do any work to manually destroy the object.
In well-written, modern C++ code, you should rarely need to manually use delete. Smart pointers and other SBRM containers should be used to manage any type of resource that needs cleanup, including dynamically allocated objects.
In your second example, given a linked list that looks like:
x -> y -> z -> 0
you would have an order of operations that looks like this:
delete x;
x.~MyClass();
delete y;
y.~MyClass();
delete z;
z.~MyClass();
delete 0;
[free memory occupied by z]
[free memory occupied by y]
[free memory occupied by x]
The objects in the linked list would be destroyed in reverse order.
delete intArray;
I assume intArray points to the first element of an int array? In that case, delete intArray yields undefined behavior. If you allocate via new[], you must release via delete[].
delete[] intArray;
Yes I know, delete intArray might appear to work just fine on certain systems with certain compiler versions under certain compiler options -- or it might not. That's undefined behavior for ya.
Also, you should follow the Rule of Three. Defining your own destructor but relying on the implicitly-defined copy constructor and copy assignment operator is a recipe for disaster.