pen
pen

Reputation: 15

What is the proper way to delete a dynamic array?

I created a 3D array t dynamically (t is of type int***). Now I am trying to delete it.

I have come across 2 suggestions: One is that simply do

delete[] t;

and apparently, it will delete everything.

The other is to do something like

for(int i=0;i<3;i++)
{
    for(int j=0;j<t1[i];j++)
    {
        delete[] t[i][j];//delete all 1D array
    }
    delete[] t[i];//delete all 2D array
}
delete[] t;//delete the 3D array

(t1 stores the size of t[i] and t2 the size of t[i][j])

what is the best way?

Upvotes: 1

Views: 8674

Answers (2)

Raindrop7
Raindrop7

Reputation: 3911

it's so important to unallocate memory properly as much as allocating it. we should be so cautious while creating a multi-dim array on the heap as much as while deleting it:

#include <iostream>
using std::cout;
using std::endl;

int main()
{

    int*** ptrInt = new int**[3];

    for(int i(0); i < 3; i++)
        ptrInt[i] = new int*[3];

    for(int i = 0; i < 3; i++)
    {
        for(int j(0); j < 3; j++)
            ptrInt[i][j] = new int[3];
    }


    for(int i = 0; i < 3; i++)
    {
        for(int j(0); j < 3; j++)
            for(int k(0); k < 3; k++)
                ptrInt[i][j][k] = k;
    }

    for(int i = 0; i < 3; i++)
    {
        for(int j(0); j < 3; j++)
            for(int k(0); k < 3; k++)
                cout << "ptrInt[" << i << "][" << j << "][" << k << "]: " << ptrInt[i][j][k] << endl;
    }

    // now freeing memory:

    for(int i = 0; i < 3; i++)
    {
        for(int j(0); j < 3; j++)
            delete[] ptrInt[i][j];
        delete[] ptrInt[i];
    }
    delete[] ptrInt;
    ptrInt = NULL; // if we call delete again on a null pointer it's ok


    cout << endl;
    return 0;
}

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372814

As @aschepler mentions in the comments, this depends on how the memory was initially allocated. I assume that you probably allocated the memory like this:

int*** t = new int**[dim1];
for (int i = 0; i < dim1; i++) {
   t[i] = new int*[dim2];
   for (int j = 0; j < dim2; j++) {
      t[i][j] = new int[dim3];
   }
}

If you allocated memory in this way, then the memory looks something like this:

                      [ 0 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                +---> [ 1 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                |     [ 2 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                |
 t ---> [ 0 ] [ 1 ]
          |
          |     [ 0 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
          +---> [ 1 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                [ 2 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]

Now, suppose that you just write

delete[] t;

If you do this, then memory will look like this:

                      [ 0 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                      [ 1 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                      [ 2 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]

 t ---> xxx

                [ 0 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                [ 1 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]
                [ 2 ] --> [ 0 ][ 1 ][ 2 ][ 3 ]

In other words, you've reclaimed one of the arrays, but you've leaked the majority of the memory. Oops!

On the other hand, if you use the for-loop version of the deletion code, you end up reclaiming all the memory because you've gone through all of the pointers and freed each array allocated.

Generally speaking, every allocation should have a matching deallocation, so if you called new[] several times, you'll need to call delete[] an equal number of times.

As some of the comments have pointed out, there are probably better ways for you to manage a 3D array than to use an int ***. The general trend in C++ is to use objects to automatically manage memory as much as possible. Consider looking into the Boost multi_array type, or consider writing a wrapper around a std::vector that stores the entries in row-major order.

Upvotes: 6

Related Questions