web-dev-qa-db-fra.com

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 interagir avec du code hérité, je peux simplement utiliser std::array::data(). Y a-t-il une raison pour laquelle je souhaiterais un tableau old-school?

85

Sauf si j'ai raté quelque chose (je n'ai pas suivi de près les modifications les plus récentes de la norme), la plupart des utilisations des tableaux de style C demeurent. std::array autorise l'initialisation statique, mais il ne compte toujours pas les initialiseurs pour vous. Et puisque la seule utilisation réelle des tableaux de style C avant std::array était pour les tableaux initialisés statiquement dans le sens de:

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

en utilisant les fonctions de modèle habituelles begin et end (adoptées en C++ 11) pour les parcourir. Sans jamais mentionner la taille, que le compilateur détermine à partir du nombre d'initialiseurs.

EDIT: Une autre chose que j'ai oublié: les littéraux de chaîne sont toujours des tableaux de style C; c'est-à-dire avec le type char[]. Je ne pense pas que quiconque exclurait d'utiliser des chaînes de caractères simplement parce que nous avons std::array.

59
James Kanze

Non, pour le dire franchement. 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 laquelle un utilisateur voudrait jamais des tableaux C. De plus, non, std::array n'est pas moins performant qu'un tableau C, et a une option pour un accès aux limites vérifiées. Et enfin, il est tout à fait raisonnable pour tout programme C++ de dépendre de la bibliothèque Standard - c'est en quelque sorte le point d'être Standard - et si vous n'avez pas accès à une bibliothèque Standard, alors votre compilateur est non conforme et le la question est étiquetée "C++", pas "C++ et ces choses non-C++ qui passent à côté de la moitié de la spécification parce qu'elles le jugeaient inapproprié.".

29
Puppy

Il semble que l'utilisation de tableaux multidimensionnels soit plus facile avec les tableaux C que std::array. Par exemple,

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

par opposition à

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

En raison également de la propriété de désintégration automatique des tableaux C, c_arr[i] dans l'exemple ci-dessus se désintègre en un pointeur et il vous suffit de passer les dimensions restantes comme deux autres paramètres. Mon point est-il c_arr n'est pas cher à copier. Toutefois, cpp_arr[i] sera très coûteux à copier.

25
Sumant

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

Une fois imbriqué, std::array Peut devenir très difficile à lire et verbeux inutilement.

Par exemple:

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

par rapport à

char c_arr[3][3]; 

Notez également que begin(), end() et size() renvoient tous des valeurs sans signification lorsque vous imbriquez std::array.

Pour ces raisons, j'ai créé mes propres conteneurs multidimensionnels de taille fixe, array_2d Et array_3d. Ils sont analogues à std::array Mais pour des tableaux multidimensionnels de 2 et 3 dimensions. Ils sont plus sûrs et n'ont pas de moins bonnes performances que les tableaux multidimensionnels intégrés. Je n'ai pas inclus de conteneur pour les tableaux multidimensionnels avec des dimensions supérieures à 3 car ils sont rares. En C++ 0x, une version de modèle variadic pourrait être créée qui prend en charge 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

13
Ricky65

Les tableaux de style C disponibles en C++ sont en réalité beaucoup moins polyvalents que les vrais tableaux C. La différence est qu'en C, les types de tableaux peuvent avoir runtime tailles. Ce qui suit est du code C valide, mais il ne peut pas être exprimé avec des tableaux de style C++ C ni avec les types C++ array<>:

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

En C++, vous devez 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;
}

Cela ne peut pas être réalisé avec std::array<>, Car bar n'est pas connu au moment de la compilation, il nécessite l'utilisation de tableaux de style C en C++ ou de std::vector<>.


Bien que le premier exemple puisse être exprimé assez facilement en C++ (bien qu'il nécessite new[] Et delete[]), Ce qui suit ne peut pas ê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 peuvent pas utiliser une 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'image exemple de manipulation 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 d'index à la main partout où les indices sont utilisés. Pour le cas 2D, cela est toujours possible (même si cela comporte de nombreuses possibilités de se tromper dans le calcul de l'indice). Cela devient vraiment méchant dans le cas 3D, cependant.

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

5
cmaster