web-dev-qa-db-fra.com

La bonne façon d'initialiser un pointeur dynamique sur un tableau multidimensionnel?

J'ai eu de la malchance avec les pointeurs dynamiques lorsque je les ai mis à 2 dimensions et plus. Par exemple, je veux un pointeur sur un tableau 2D. Je le sais:

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

Est complètement légitime (même si je ne comprends pas complètement pourquoi). Tenant compte du fait que:

int *P = new int[4];

fonctionne, j’imaginais que:

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

Fonctionnerait également, mais ce n'est pas le cas. Ce code indique l'erreur:

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

En voyant cela, la nouvelle partie devient un pointeur vers un tableau de 7 entiers que j'ai fait:

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

Et cela fonctionne, mais ce n'est pas ce que je veux accomplir. En le faisant comme ça, je suis limité à au moins utiliser une valeur constante pour toute dimension ultérieure, mais je veux qu'elle soit entièrement définie au moment de l'exécution et donc "dynamique".

Comment pourrais-je aller et faire fonctionner ce pointeur multidimensionnel ??

26
Jader J Rivera

Commençons par quelques exemples de base.

Quand tu dis int *P = new int[4];

  1. new int[4]; appelle la nouvelle fonction de l'opérateur ()
  2. alloue une mémoire à 4 entiers.
  3. renvoie une référence à cette mémoire.
  4. pour lier cette référence, vous devez avoir le même type de pointeur que celui de la référence de retour, donc

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

Pour un tableau multidimensionnel, vous devez allouer un tableau de pointeurs, puis remplir ce tableau de pointeurs vers des tableaux, comme ceci:

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
}

Voici à quoi cela ressemble:

enter image description here

Pour libérer la mémoire

  1. Pour un tableau unidimensionnel,

     // need to use the delete[] operator because we used the new[] operator
    delete[] p; //free memory pointed by p;`
    
  2. Pour le tableau 2D,

    // 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;
    

Évitez fuite de mémoire et pointeurs pendants!

68
Dipak Ingole

Vous voulez quelque chose comme:

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

Une autre approche consisterait à utiliser un tableau 1D comme tableau 2D. De cette façon, vous n'avez à allouer la mémoire qu'une seule fois (un bloc continu);

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

Il en résulterait la même chose que "int array [5] [5]".

pour accéder aux champs que vous venez de faire:

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

Cela équivaut à:

array[1][2];
2
the baconing

Cela vérifie les limites de certains compilateurs de débogage, utilise la taille dynamique et se supprime automatiquement. Le seul problème est x et y sont l'inverse.

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;
    }
}
2
Neil Kirk