static_assert(sizeof(std::array)==5*sizeof(int));
ce qui précède atténue tout ajout de rembourrage à la fin d'un std::array
. Aucun compilateur majeur n'a à ce jour échoué à ce qui précède, et je parie qu'ils ne le feront pas à l'avenir.
Si et seulement si ce qui précède échoue, alors std::vector> v(2)
aura un "écart" entre les std::array
s.
Cela ne aide pas autant que vous le voudriez; un pointeur généré comme suit :
int* ptr = &v[0][0];
n'a une validité que jusqu'à ptr+5
, et le déréférencement de ptr+5
est un comportement indéfini.
Cela est dû aux règles d'aliasing; vous n'êtes pas autorisé à "marcher" au-delà de la fin d'un objet dans un autre, même si vous savez qu'il est là, à moins de faire d'abord un aller-retour vers certains types (comme char*
) où des calculs de pointeurs moins restrictifs sont autorisés.
Cette règle existe pour permettre aux compilateurs de raisonner sur les données auxquelles on accède à travers quel pointeur, sans avoir à prouver que des calculs de pointeurs arbitraires vous permettront d'atteindre des objets extérieurs.
Donc:
struct bob {
int x,y,z;
};
bob b {1,2,3};
int* py = &b.y;
peu importe ce que vous faites avec py
en tant qu'int*
, vous ne pouvez pas légalement modifier x
ou z
avec celui-ci.
*py = 77;
py[-1]=3;
std::cout << b.x;
le compilateur peut optimiser la ligne std::cout
pour simplement afficher 1
, car py[-1]=3
peut tenter de modifier b.x
, mais le faire de cette manière est un comportement indéfini.
Le même type de restrictions vous empêche de passer du premier tableau de votre std::vector
au second (c'est-à-dire au-delà de ptr+4
).
Créer ptr+5
est autorisé, mais seulement en tant que pointeur d'un élément après la fin. Comparer ptr+5 == &v[1][0]
n'est pas non plus spécifié dans le résultat, même si leurs valeurs binaires vont absolument être identiques dans tous les compilateurs sur tous les principaux systèmes matériels.
Si vous voulez aller plus loin dans le terrier du lapin, il n'est même pas possible de mettre en œuvre std::vector
en C++ lui-même en raison de ces restrictions sur l'aliasing des pointeurs. La dernière fois que j'ai vérifié (avant c++17, mais je n'ai pas vu de résolution dans C++17) le comité standard travaillait à résoudre ce problème, mais je ne connais pas l'état de cet effort. (Ceci est moins un problème que vous pourriez le penser, car rien n'exige que std::vector
soit implémenté en C++ conforme aux normes; il doit simplement avoir un comportement défini par les normes. Il peut utiliser des extensions spécifiques au compilateur en interne.)
0 votes
Étant donné les réponses, si vous voulez ceci, utilisez
std::vector vec(5*2)
et effectuez l'indexation 2D vous-même à l'intérieur du tableau 1D plat. Peut-être écrire une classe d'enveloppe pour l'indexation 2D au-dessus d'un conteneur plat, avec une longueur de ligne templatisée ou variable au moment de l'exécution. Vous voudriez également exposer une vue plate afin que les algorithmes qui ont juste besoin de faire quelque chose à chaque élément sans se soucier de la position 2D puissent le faire avec une seule grande boucle, de manière plus efficace.