85 votes

Maintenant que nous avons std::array, quelles sont les utilisations restantes pour les tableaux de style C ?

std::array est largement supérieur aux tableaux C. Et même si je veux interopérer avec du code existant, je peux simplement utiliser std::array::data() . Y a-t-il une raison pour que je veuille un tableau old-school ?

59voto

James Kanze Points 96599

À moins que j'aie manqué quelque chose (je n'ai pas suivi de très près les dernières modifications de la norme), la plupart des utilisations des tableaux de style C demeurent. std::array permet l'initialisation statique, mais il ne compte toujours pas les initialisateurs pour vous. Et puisque la seule utilisation réelle des tableaux de style C avant std::array était pour les tables initialisées statiquement du genre :

MyStruct const table[] =
{
    { something1, otherthing1 },
    //  ...
};

en utilisant l'habituel begin y end (adoptées dans C++11) pour les itérer. Sans jamais mentionner la taille, que le compilateur détermine à partir du nombre d'initialisateurs.

EDIT : Autre chose que j'ai oublié : les chaînes de caractères sont toujours des tableaux de style C ; c'est-à-dire avec le type char[] . Je ne pense pas que quelqu'un exclurait l'utilisation de chaînes de caractères simplement parce que nous disposons de std::array .

30voto

Puppy Points 90818

Non. Pour, euh, le dire crûment. Et en 30 caractères.

Bien sûr, vous avez besoin de tableaux C pour implémenter std::array mais ce n'est pas vraiment une raison pour qu'un utilisateur veuille des tableaux C. En outre, non, std::array n'est pas moins performant qu'un tableau C, et a une option pour un accès contrôlé par les limites. Et enfin, il est tout à fait raisonnable pour tout programme C++ de dépendre de la bibliothèque standard - c'est en quelque sorte l'intérêt d'être standard - et si vous n'avez pas accès à une bibliothèque standard, alors votre compilateur est non-conforme et la question est étiquetée "C++", et non "C++ et ces choses pas C++ qui manquent la moitié de la spécification parce qu'ils ont estimé que c'était inapproprié".

25voto

Sumant Points 2294

Il semble qu'il soit plus facile d'utiliser des tableaux multidimensionnels avec des tableaux C qu'avec des tableaux C. std::array . Par exemple,

char c_arr[5][6][7];

à l'opposé de

std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;

En raison également de la propriété de décroissance automatique des tableaux C, c_arr[i] dans l'exemple ci-dessus se décomposera en un pointeur et il vous suffira de passer les dimensions restantes comme deux paramètres supplémentaires. Ce que je veux dire, c'est que c_arr n'est pas coûteux à copier. Cependant, cpp_arr[i] sera très coûteux à copier.

13voto

Ricky65 Points 538

Comme l'a dit Sumant, les tableaux multidimensionnels sont beaucoup plus faciles à utiliser avec les tableaux intégrés en C qu'avec les tableaux de l'UE. std::array .

Lorsqu'ils sont imbriqués, std::array peut devenir très difficile à lire et inutilement verbeux.

Par exemple :

std::array<std::array<int, 3>, 3> arr1; 

par rapport à

char c_arr[3][3]; 

Notez également que begin() , end() y size() renvoient tous des valeurs sans signification lorsque l'on emboîte std::array .

Pour ces raisons, j'ai créé mes propres conteneurs de tableaux multidimensionnels à taille fixe, array_2d y array_3d . Ils sont analogues à std::array mais pour les tableaux multidimensionnels de 2 et 3 dimensions. Ils sont plus sûrs et ne sont pas moins performants que les tableaux multidimensionnels intégrés. Je n'ai pas inclus de conteneur pour les tableaux multidimensionnels de dimensions supérieures à 3, car ils sont peu courants. En C++0x, il était possible de créer une version variadique du modèle qui supporte un nombre arbitraire de dimensions.

Un exemple de la variante bidimensionnelle :

//Create an array 3 x 5 (Notice the extra pair of braces) 

fsma::array_2d <double, 3, 5> my2darr = {{
    { 32.19, 47.29, 31.99, 19.11, 11.19},
    { 11.29, 22.49, 33.47, 17.29, 5.01 },
    { 41.97, 22.09, 9.76, 22.55, 6.22 }
}};

La documentation complète est disponible ici :

http://fsma.googlecode.com/files/fsma.html

Vous pouvez télécharger la bibliothèque ici :

http://fsma.googlecode.com/files/fsma.zip

5voto

cmaster Points 7460

Les tableaux de style C disponibles en C++ sont en fait beaucoup moins polyvalents que les tableaux C réels. La différence est qu'en C, les types de tableau peuvent avoir temps de fonctionnement tailles. Le code suivant est un code C valide, mais il ne peut être exprimé ni avec les tableaux de style C++ ni avec le langage C++. array<> types :

void foo(int bar) {
    double tempArray[bar];
    //Do something with the bar elements in tempArray.
}

En C++, vous auriez dû allouer le tableau temporaire sur le tas :

void foo(int bar) {
    double* tempArray = new double[bar];
    //Do something with the bar elements behind tempArray.
    delete[] tempArray;
}

Cet objectif ne peut être atteint avec std::array<> parce que bar n'est pas connue au moment de la compilation, elle nécessite l'utilisation de tableaux de type C en C++ ou de tableaux de type B en C++. std::vector<> .


Alors que le premier exemple pourrait relativement facilement être exprimé en C++ (bien que nécessitant new[] y delete[] ), ce qui suit ne peut être réalisé en C++ sans std::vector<> :

void smoothImage(int width, int height, int (*pixels)[width]) {
    int (*copy)[width] = malloc(height*sizeof(*copy));
    memcpy(copy, pixels, height*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y][x] = //compute smoothed value based on data around copy[y][x]
        }
    }
    free(copy);
}

Le fait est que les pointeurs vers les tableaux de lignes int (*)[width] ne peut pas utiliser de largeur d'exécution en C++, ce qui rend tout code de manipulation d'image beaucoup plus compliqué en C++ qu'en C. Une implémentation C++ typique de l'exemple de manipulation d'image ressemblerait à ceci :

void smoothImage(int width, int height, int* pixels) {
    int* copy = new int[height*width];
    memcpy(copy, pixels, height*width*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
        }
    }
    delete[] copy;
}

Ce code effectue précisément les mêmes calculs que le code C ci-dessus, mais il doit effectuer le calcul de l'indice à la main. partout où les indices sont utilisés . Pour le cas 2D, c'est encore faisable (même si cela s'accompagne de nombreuses possibilités de se tromper dans le calcul de l'indice). Mais cela devient vraiment désagréable dans le cas de la 3D.

J'aime écrire du code en C++. Mais chaque fois que je dois manipuler des données multidimensionnelles, je me demande vraiment si je dois déplacer cette partie du code vers le C.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X