The correct way to initialize a dynamic pointer to a multidimensional array?

84,479

Solution 1

Let's start with some basic examples.

When you say int *P = new int[4];

  1. new int[4]; calls operator new function()
  2. allocates a memory for 4 integers.
  3. returns a reference to this memory.
  4. to bind this reference, you need to have same type of pointer as that of return reference so you do

    int *P = new int[4]; // As you created an array of integer
                         // you should assign it to a pointer-to-integer
    

For a multi-idimensional array, you need to allocate an array of pointers, then fill that array with pointers to arrays, like this:

int **p;
p = new int*[5]; // dynamic `array (size 5) of pointers to int`

for (int i = 0; i < 5; ++i) {
  p[i] = new int[10];
  // each i-th pointer is now pointing to dynamic array (size 10)
  // of actual int values
}

Here is what it looks like:

enter image description here

To free the memory

  1. For one dimensional array,

     // need to use the delete[] operator because we used the new[] operator
    delete[] p; //free memory pointed by p;`
    
  2. For 2d Array,

    // need to use the delete[] operator because we used the new[] operator
    for(int i = 0; i < 5; ++i){
        delete[] p[i];//deletes an inner array of integer;
    }
    
    delete[] p; //delete pointer holding array of pointers;
    

Avoid memory leakage and dangling pointers!

Solution 2

You want something like:

int **P = new int*[7];
p[0] = new int[5];
p[1] = new int[5];
...

Solution 3

Another approach would be to use a 1D array as an 2D array. This way you only have to allocate the memory once (one continous block);

int *array;
size_t row=5,col=5;
array = (int*)malloc(row*col*sizeof(int)) //or new int[row*col]

This would result in the same as "int array[5][5]".

to access the fields you just do:

array[1 //the row you want
 * col //the number of columns
+2//the column you want
] = 4;

This is equal to:

array[1][2];

Solution 4

This performs bounds checking on some debug compilers, uses dynamic size and deletes itself automatically. The only gotcha is x and y are the opposite way round.

std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size));

for (int y = 0; y < y_size; y++)
{
    for (int x = 0; x < x_size; y++)
    {
        array2d[y][x] = 0;
    }
}
Share:
84,479

Related videos on Youtube

Jader J Rivera
Author by

Jader J Rivera

Updated on May 02, 2020

Comments

  • Jader J Rivera
    Jader J Rivera about 4 years

    I've been having bad luck with with dynamic pointers when I range them to 2 dimensions and higher. For example I want a pointer to a 2D array. I know that:

    int A[3][4];
    int (*P)[4] = A;
    

    Is completely legit (even if I don't completely understand why). Taking into consideration that:

    int *P = new int[4];
    

    works, I imagined that:

    int **P = new int[5][7];
    

    Would also work, but it's not. This code states the error:

    Error: A value of type "(*)[7]" cannot be used to initialize an entity of
           type "int **"
    

    By seeing this the new part becomes a pointer to an array of 7 integers I made:

    int (*P)[4] = new int[7][4];
    

    And this does work but it's not what I want to accomplish. By doing it like that I'm limited to at least using a constant value for any subsequent dimension, but I want it to be fully defined at run time and therefore "dynamic".

    How could I go and make this multidimensional pointer work??

    • doctorlove
      doctorlove almost 11 years
      Don't forget to delete them
    • Chad
      Chad almost 11 years
      std::vector<std::unique_ptr<int>>
  • Ben Voigt
    Ben Voigt over 9 years
    No it does not perform bounds checking.
  • Kalyan Saha
    Kalyan Saha about 3 years
    Initialisation can be done following way also. std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size, 0));
  • Kalyan Saha
    Kalyan Saha about 3 years
    Also there is a issue with 2nd for loop. There should be x++ instead of y++