Mark Miles
Mark Miles

Reputation: 706

C++ delete[] vs. delete in array of arrays

I know that if I use new[] I have to delete[], but this is my doubt:

Declaration:

char **data; // This will be a bi-dimensional array

Construct:

data = new char*[10];
for (int i=0; i<10; ++i) 
{
  data[i] = new char[128];
}

Destroy:

for (int i=0; i<10; ++i) 
{
  delete data[i]; // <--- delete or delete[] ???
}
delete[] data;

Another case where I have an array of objects:

Declaration:

myClass **object;

Construct:

object = new myClass*[10];
for (int i=0; i<10; ++i) 
{
  object[i] = new myClass();
}

Destroy:

for (int i=0; i<10; ++i) 
{
  delete object[i]; // <--- this object[] is not an array, right?
}
delete[] object; // <--- Is this correct?

Upvotes: 2

Views: 2490

Answers (3)

MichaelCMS
MichaelCMS

Reputation: 4763

The mnemonic that you mentioned (delete [] for new [] and delete for new) is a a good practice, and should be enforced as mandatory.

However, there is a huge difference between delete and delete[] when it comes to base types (int, char, void*,etc) and classes.

The difference between new and malloc is that one calls the constructor while the other doesn't. Same relation happens with delete and free when it comes to destructor.

In your example you gave two situations : one when an array of simple type is allocated and one with an array of objects allocated.

The behavior is different.

For the simple type, delete and delete[] will produce the same result .

Reason ? well, you basically allocated a block of 10 pointers of char* , so deleting it is no problem (the allocated memory paged will be freed).

In other words, if you have

 char* a = new char[100];

then

 delete a;

and

 delete[] a;

will produce the same results (note that you used a new []);

This behavior is different when it comes to objects that have constructors and destructors.

Let's take the following class :

class SimpleClass
{
   public:
         SimpleClass(){printf("constructed");
         ~SimpleClass()(printf("destructed");
}

and the following code :

SimpleClass* arr1 = new SimpleClass[5];
SimpleClass* arr2 = new SimpleClass[5];
char* arr3 = new char[5];
char* arr4 = new char[5];

delete[] arr4;
delete arr3;
delete[] arr2;
delete arr1; //notice the surprise ?

Run the above code (if you can) in Visual Studio and open up a memory viewer. You will see that the memory allocated at ptrs arr4 and arr3 is correctly invalidated, same for arr2.

However when attempting to delete arr1 without the [] call you will get a SigSev error .

Why ?

Because in case of arr2 you have an array of allocated objects, and the delete[] statement means "pass through each destructor from the array"".

In case of arr1 it means : call the destructor of the object allocated at pointer arr1... a bit unfortunate if you take into account that there is more then 1 object allocated at that address, and you end up attempting to release a page which is lesser then the initial allocated size.

Bottom line :

delete[] for new[] and delete for new !

Works every time !

Upvotes: 0

ctzdev
ctzdev

Reputation: 676

The first dimension of your pointer data is an array. The second dimension is an array as well. Therefore you must use delete[] to properly deallocate memory reserved from your new[].

For your object, the first dimension was allocated using new. So you must use delete. Then use delete[] on object because it's an array.

Upvotes: 1

Rahul Manne
Rahul Manne

Reputation: 1249

You basically answered your own question. Since data[i] is an array, you need to delete[]. object[i] was allocated with new so you would delete it. Since both object and data are arrays, you would need to delete[] them.

Upvotes: 4

Related Questions