简体   繁体   中英

What's the proper way to pass a pointer to a function for deletion?

I have a matrix declared like int **matrix , and I know that the proper way to pass it to a function to allocate memory should be like this:

void AllocMat(int ***mat, int size);

But now I need to delete these memory in another function and am not sure about what to pass:

void DeallocMat(int **mat, int size);

or

void DeallocMat(int ***mat, int size);

I think the second one should be right, but neither way gives me segmentation fault as I tried.

First is correct. But your real problem is that you are using pointers when there are better alternatives. For a 2d matrix you should use a vector of vectors

#include <vector>

typedef std::vector<std::vector<int> > Matrix;

Matix m;

Now there is no need to delete anything, so one less thing to go wrong.

The question is tagged C++, and yet the answers only use the C subset...

Well, first of all, I would recommend against the whole thing. Create a class that encapsulates your matrix and allocate it in a single block, offer operator()(int,int) to gain access to the elements...

But back to the problem. In C++ you should use references rather than pointers to allow the function to change the argument, so your original allocate signature should be:

void AllocMat(int **&mat, int size);

And call it like:

int **matrix = 0;
AllocMat( matrix, 5 );

Or better, just return the pointer:

int **AllocMat( int size );
int **matrix = AllocMat( 5 );

For the deallocation function, since you don't need to modify the outer pointer, you can just use:

void DeallocMat( int**mat, int size ); // size might be required to release the 
                                       // internal pointers

Now, for a sketch of the C++ solution:

template <typename T>                   // no need to limit this to int
class square_matrix {
   const unsigned size;
   T * data;
public:
   square_matrix( unsigned size ) : size(size), data( new T[size*size]() ) {}
   square_matrix( matrix const & m ) : size( m.size ), data( new T[m.size*m.size] ) {
      std::copy( m.data, m.data+size*size, data );
   }
   ~matrix() {
      delete [] data;
   }
   T const & operator()( unsigned x, unsigned y ) const {
      // optional range check and throw exception
      return data[ x + y*size ];
   }
   void set( unsigned x, unsigned y, T const & value ) {
      // optional range check and throw exception
      data[ x + y*size ] = value;
   }
};

void DeallocMat(int **mat, int size) - allows you to deallocate memory (since you have passed the value of mat only allowing to deallocate memory but not change mat )

void DeallocMat(int ***mat, int size) - allows you to deallocate memory and change the value of mat to NULL (since you have now passed a pointer to mat allowing you to change its value)

The extra "*" just handles the pointer to be behaved as call by reference . If you want to get the output from your function, you need an extra "*" in your declaration. In this case, you should pass the reference of your pointer (using &) to these functions.

Either way works, but if you pass a pointer to the pointer you need to dereference it first. And the size parameter is redundant.

void DeallocMat(int **mat)
{
    delete[] mat;
}

void DeallocMat(int ***mat)
{
    delete[] *mat;
    *mat = NULL;
}

The reason why you required to pass a pointer to double pointer because your local variable must required to reflect with the new updated memory

void Foo(int * a)
{
   a = new int[10];
}
int main()
{
   int *a = 0;
   Foo( a );
}

Now the memory will be allocated but the pointer A will not be update because the value of pointer A is simply copied to another pointer variable which is parameter of Foo. Once the Foo is returned, a will remain 0. To make it refect that, you should write code like follows

void Foo(int ** a)
{
   *a = new int[10];
}
int main()
{
   int *a = 0;
   Foo( &a );
}

Here you're passing the address of a pointer. The which means that, the value which contains in the pointer will be updated from the Foo function.You can debug through and see how it works.

If you're sure that you will not access the pointer anymore, please use the first type. Otherwise use the second one. Make sure that you set the pointer to NULL to avoid further memory corruptions or dangling pointers.

The thing that confuses me about your question is that most people would not declare a matrix as an int ** . The reason for this is that you would be forced to then allocate it in a loop. Your allocation function would require two parameters, which are the dimensions of the array like this:

void AllocMat(int *** mat, int n, int m) {
    int ** result = new int * [ n ];
    for (int x=0; x<n; x++) {
        result[x] = new int [ m ];
    }
    *mat = result;
}

If this were the case, the corresponding deallocation function would require knowledge of the size of n as follows:

void DeallocMat(int *** mat, int n) {
    if (mat == NULL || *mat == NULL) return;
    int ** tmp = *mat;
    for (int x=0; x<n; x++) {
        if (tmp[x] != NULL) delete [] tmp[x];
    }
    delete [] tmp;
    *mat = NULL;
}

With this approach, you could access your matrix like this:

int ** mat = NULL;
AllocMat(&mat, n, m);

for (int x=0; x<n; x++) {
    for (int y=0; y<m; y++) {
        mat[x][y] = 1;
    }
}

DeallocMat(&mat, n);

Usually, people allocate matrices as a single buffer of memory to avoid extra allocations and pointer indirections, which is how I recommend you do it. In that case, you allocation function would look like this:

void AllocMat2(int ** mat, int n, int m) {
        *mat = new int [ n * m ];
}

And the corresponding deallocation function like this:

void DeallocMat2(int ** mat) {
    if (mat != NULL && *mat != NULL) {
        delete [] *mat;
        *mat = NULL;
    }
}

And you would access it follows:

int * mat2 = NULL;
AllocMat2(&mat2, n, m);

for (int x=0; x<n; x++) {
    for (int y=0; y<m; y++) {
        mat2[x * n + y] = 1;
    }
}

DeallocMat2(&mat2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM