std::array
est largement supérieur aux tableaux C. Et même si je veux interagir avec le code hérité, je peux simplement utiliser std::array::data()
. Y a-t-il une raison pour laquelle je voudrais un jour un tableau à l'ancienne?
std::array
est largement supérieur aux tableaux C. Et même si je veux interagir avec le code hérité, je peux simplement utiliser std::array::data()
. Y a-t-il une raison pour laquelle je voudrais un jour un tableau à l'ancienne?
Réponses:
À moins d'avoir manqué quelque chose (je n'ai pas suivi de trop près les changements les plus récents de la norme), la plupart des utilisations des tableaux de style C subsistent. std::array
autorise l'initialisation statique, mais ne compte toujours pas les initialiseurs à votre place. Et comme la seule véritable utilisation des tableaux de style C auparavant std::array
était pour les tables initialisées statiquement comme:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
en utilisant les fonctions habituelles begin
et de end
modèle (adoptées en C ++ 11) pour les parcourir. Sans jamais parler de la taille, que le compilateur détermine à partir du nombre d'initialiseurs.
EDIT: Une autre chose que j'ai oubliée: les chaînes littérales sont toujours des tableaux de style C; c'est à dire avec le type char[]
. Je ne pense pas que quiconque exclurait l'utilisation de chaînes littérales simplement parce que nous l'avons fait std::array
.
const char[]
Non, euh, dis-le 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 un tableau C. De plus, non, std::array
n'est pas moins performant qu'un tableau C et dispose d'une option pour un accès vérifié 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 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 les choses non-C ++ qui manquent la moitié de la spécification parce qu'elles la jugent inappropriée.".
std::array
dans une implémentation autonome C ++ 11.
On dirait que l'utilisation de tableaux multidimensionnels est 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;
Également en raison de la propriété de décroissance automatique des tableaux C, c_arr[i]
dans l'exemple ci-dessus, la décomposition en un pointeur se fera et il vous suffit de passer les dimensions restantes comme deux paramètres supplémentaires. Mon point est que la c_arr
copie n'est pas coûteuse. Cependant, la cpp_arr[i]
copie sera très coûteuse.
array
à une fonction sans perdre de dimensions. Et si vous le transmettez à un modèle de fonction, cette fonction peut déduire à la fois la dimension et la taille de chaque dimension, ou juste l'une des deux. Cela peut être intéressant pour les bibliothèques de modèles scientifiques qui travaillent principalement sur des dimensions arbitraires.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
devrait résoudre l'un de ces problèmes.
c_arr
est très coûteux à copier! Vous devez fournir le code pour le faire vous-même. Le pointeur vers lequel il se désintègre est un équivalent plus proche d'une référence qu'une copie et vous pouvez l'utiliser std::array
pour passer une référence si c'est ce que vous voulez.
std::size_t
place int
? désolé pour pinailler, mais cela le rendrait universel.
size_t
si vous le souhaitez, même si je ne peux pas imaginer qu'il existe de nombreux scénarios où des tableaux de plus de 4 milliards de lignes ou de colonnes sont nécessaires.
Comme Sumant l'a dit, les tableaux multidimensionnels sont beaucoup plus faciles à utiliser avec les tableaux C intégrés qu'avec std::array
.
Lorsqu'elles sont imbriquées, elles std::array
peuvent devenir très difficiles à lire et inutilement verbeuses.
Par exemple:
std::array<std::array<int, 3>, 3> arr1;
par rapport à
char c_arr[3][3];
Notez également que begin()
, end()
et size()
tous renvoient des valeurs sans signification lorsque vous imbriquez std::array
.
Pour ces raisons, j'ai créé mes propres conteneurs de tableaux 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 pires 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 variadique peut ê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:
arr[x][y]
, vous ne pouvez pas dire s'il arr
s'agit d'un tableau de tableaux, d'un tableau de pointeurs, d'un pointeur vers un tableau ou d'un pointeur vers un pointeur; tout pour les implémentations sont légitimes, en fonction de vos besoins. Et probablement la plupart des cas d'utilisation réels pour les tableaux multidimensionnels nécessitent que la taille soit déterminée au moment de l'exécution.
Les tableaux de style C qui sont disponibles en C ++ sont en fait beaucoup moins polyvalents que les véritables tableaux C. La différence est qu'en C, les types de tableaux peuvent avoir des tailles d' exécution . Ce qui suit est du code C valide, mais il ne peut être exprimé ni avec des tableaux de style C C ++ ni avec les array<>
types C ++ :
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
En C ++, vous devrez 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 ce bar
n'est pas connu au moment de la compilation, cela nécessite l'utilisation de tableaux de style C en C ++ ou de std::vector<>
.
Alors que le premier exemple pourrait être relativement facilement exprimé en C ++ (bien que nécessitant 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'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 fait exactement 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 faisable (même si cela offre de nombreuses possibilités de se tromper dans le calcul de l'indice). Cela devient vraiment méchant dans le cas de la 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 vers C.
gcc
par exemple). C11 a rendu facultatifs un certain nombre de choses intéressantes, et je ne pense pas que ce soit parce qu'ils veulent interdire cette fonctionnalité. J'ai tendance à voir cela comme un signe qu'ils voulaient abaisser le niveau d'écriture d'un compilateur entièrement conforme aux normes: les VLA sont assez difficiles à implémenter, et beaucoup de code peut s'en passer, il est donc logique pour un nouveau compilateur sur un nouveau plate-forme pour ne pas avoir à mettre en œuvre les VLA tout de suite.
Peut-être que le std::array
n'est pas lent. Mais j'ai fait des analyses comparatives en utilisant simple store et en lisant depuis le std :: array; Voir les résultats de référence ci-dessous (sur W8.1, VS2013 Update 4):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
Selon les marques négatives, le code que j'ai utilisé est dans le pastebin ( lien )
Le code de classe de référence est ici ;
Je ne sais pas grand-chose sur les benchmarks ... Mon code est peut-être défectueux
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
maintenant. Vous devez vraiment sauter à travers des cercles pour vous assurer que le code que vous mesurez est le code que vous souhaitez mesurer.
std::array
std::array
sera moins performant qu'un tableau C.
at()
dedans, ce n'est pas dedans operator[]
, juste comme std::vector
. Il n'y a pas de diminution des performances ou de gonflement du code std::array
, le compilateur est conçu pour optimiser ce genre de chose. Et, bien sûr, l'ajout de la fonction vérifiée est un excellent outil de débogage et un grand avantage. @Lou Franco: Tout le code C ++ peut dépendre de la bibliothèque Standard - c'est un peu ce à quoi il sert. @Earlz: Si vous n'avez pas STL disponible, alors ce n'est pas C ++, et c'est la fin de cela.
std::array
soit plus grande que l'utilisation du tableau C équivalent.