Quelle est la différence entre un std::vector
et un std::array
en C ++? Quand faut-il préférer un autre? Quels sont les avantages et les inconvénients de chacun? Tout ce que mon manuel fait est de lister comment ils sont les mêmes.
283
std::vector
vsstd::array
et comment les termes sont différents.std::array
n'est pas la même chose qu'un tableau C ++.std::array
est un wrapper très fin autour des tableaux C ++, dont le but principal est de cacher le pointeur à l'utilisateur de la classe. Je mettrai à jour ma réponse.Réponses:
std::vector
est une classe de modèle qui encapsule un tableau dynamique 1 , stocké dans le tas, qui grandit et se rétrécit automatiquement si des éléments sont ajoutés ou supprimés. Il fournit tous les crochets (begin()
,end()
, itérateurs, etc.) qui le font fonctionner très bien avec le reste de la STL. Il dispose également de plusieurs méthodes utiles qui vous permettent d'effectuer des opérations qui, sur un tableau normal, seraient fastidieuses, comme par exemple l'insertion d'éléments au milieu d'un vecteur (il gère tout le travail de déplacement des éléments suivants dans les coulisses).Puisqu'il stocke les éléments en mémoire alloués sur le tas, il a une surcharge en ce qui concerne les tableaux statiques.
std::array
est une classe de modèle qui encapsule un tableau de taille statique, stocké à l'intérieur de l'objet lui-même, ce qui signifie que si vous instanciez la classe sur la pile, le tableau lui-même sera sur la pile. Sa taille doit être connue au moment de la compilation (elle est transmise en tant que paramètre de modèle), et elle ne peut pas augmenter ou diminuer.Il est plus limité que
std::vector
, mais il est souvent plus efficace, en particulier pour les petites tailles, car en pratique, il s'agit principalement d'un wrapper léger autour d'un tableau de style C. Cependant, il est plus sécurisé, car la conversion implicite en pointeur est désactivée, et il fournit une grande partie des fonctionnalités liées à STLstd::vector
et des autres conteneurs, vous pouvez donc l'utiliser facilement avec les algorithmes & co STL. Quoi qu'il en soit, pour la limitation même de la taille fixe, il est beaucoup moins flexible questd::vector
.Pour une introduction à
std::array
, consultez cet article ; pour une introduction rapide àstd::vector
et aux opérations qui y sont possibles, vous pouvez consulter sa documentation .En fait, je pense que dans la norme elles sont décrites en termes de complexité maximale des différentes opérations (ex: accès aléatoire en temps constant, itération sur tous les éléments en temps linéaire, ajout et suppression d'éléments à la fin en temps amorti constant, etc), mais AFAIK il n'y a pas d'autre méthode pour répondre à ces exigences que d'utiliser un tableau dynamique.Comme indiqué par @Lucretiel, la norme exige en fait que les éléments soient stockés de manière contiguë, il s'agit donc d' un tableau dynamique, stocké là où l'allocateur associé le place.la source
static
mot-clé même en C ++ a trois significations différentes sans rapport, et le terme est également souvent utilisé pour parler de choses qui sont fixées au moment de la compilation. J'espère que "de taille statique" est un peu plus clair.Utilisation de la
std::vector<T>
classe:... est aussi rapide que d'utiliser des tableaux intégrés, en supposant que vous ne faites que ce que les tableaux intégrés vous permettent de faire (lire et écrire sur des éléments existants).
... se redimensionne automatiquement lorsque de nouveaux éléments sont insérés.
... vous permet d'insérer de nouveaux éléments au début ou au milieu du vecteur, "décalant" automatiquement le reste des éléments "vers le haut" (cela a-t-il un sens?). Il vous permet de supprimer des éléments n'importe où dans le
std::vector
, en déplaçant automatiquement le reste des éléments vers le bas.... vous permet d'effectuer une lecture vérifiée par plage avec la
at()
méthode (vous pouvez toujours utiliser les indexeurs[]
si vous ne voulez pas que cette vérification soit effectuée).Il y a
deuxtrois mises en garde principales à utiliserstd::vector<T>
:Vous n'avez pas un accès fiable au pointeur sous-jacent, ce qui peut être un problème si vous traitez avec des fonctions tierces qui demandent l'adresse d'un tableau.
La
std::vector<bool>
classe est idiote. Il est implémenté comme un champ binaire condensé, pas comme un tableau. Évitez-le si vous voulez un tableau debool
s!Pendant l'utilisation, les
std::vector<T>
s vont être un peu plus grands qu'un tableau C ++ avec le même nombre d'éléments. En effet, ils doivent garder une trace d'une petite quantité d'autres informations, telles que leur taille actuelle, et parce que chaque foisstd::vector<T>
qu'ils redimensionnent, ils réservent plus d'espace qu'ils n'en ont besoin. Cela leur évite d'avoir à redimensionner chaque fois qu'un nouvel élément est inséré. Ce comportement peut être modifié en fournissant une personnalisationallocator
, mais je n'ai jamais ressenti le besoin de le faire!Edit: Après avoir lu la réponse de Zud à la question, j'ai pensé que je devrais ajouter ceci:
La
std::array<T>
classe n'est pas identique à un tableau C ++.std::array<T>
est un wrapper très fin autour des tableaux C ++, dans le but principal de cacher le pointeur à l'utilisateur de la classe (en C ++, les tableaux sont implicitement convertis en pointeurs, souvent avec un effet consternant). Lastd::array<T>
classe stocke également sa taille (longueur), ce qui peut être très utile.la source
data()
unstd::vector<T>
pour obtenir le pointeur sous-jacent. Vous pouvez également simplement prendre l'adresse de l'élément 0 (garanti pour fonctionner avec C ++ 11, fonctionnera probablement avec les versions antérieures).Pour souligner un point soulevé par @MatteoItalia, la différence d'efficacité est l'endroit où les données sont stockées. La mémoire de tas (requise avec
vector
) nécessite un appel au système pour allouer de la mémoire et cela peut être coûteux si vous comptez des cycles. La mémoire de pile (possible pourarray
) est virtuellement "sans surcharge" en termes de temps, car la mémoire est allouée en ajustant simplement le pointeur de pile et elle n'est effectuée qu'une seule fois lors de l'entrée dans une fonction. La pile évite également la fragmentation de la mémoire. Pour être sûr,std::array
ne sera pas toujours sur la pile; cela dépend de l'endroit où vous l'allouez, mais cela impliquera toujours une allocation de mémoire de moins du tas par rapport au vecteur. Si tu as uncertainement utiliser un
std::array
sur un vecteur. Si l'une de ces exigences n'est pas vraie, utilisez astd::vector
.la source
new std::array
ou en fait un membre d'une classe que vous utilisez «nouveau» pour allouer.new std::array
qu'il s'attend toujours à connaître sa taille au moment de la compilation et ne peut pas changer sa taille mais vit toujours sur le tas?new std::array
vsnew std::vector
.Si vous envisagez d'utiliser des tableaux multidimensionnels, il existe une différence supplémentaire entre std :: array et std :: vector. Un tableau std :: array multidimensionnel aura les éléments emballés en mémoire dans toutes les dimensions, tout comme le tableau de style alternatif. Un std :: vector multidimensionnel ne sera pas compressé dans toutes les dimensions.
Compte tenu des déclarations suivantes:
Un pointeur vers le premier élément du tableau de style c (cConc) ou du tableau std :: (aConc) peut être itéré dans tout le tableau en ajoutant 1 à chaque élément précédent. Ils sont bien emballés.
Un pointeur vers le premier élément du tableau vectoriel (vConc) ou du tableau de pointeurs (ptrConc) ne peut être itéré que par les 5 premiers éléments (dans ce cas), puis il y a 12 octets (sur mon système) de surcharge pour le vecteur suivant.
Cela signifie qu'un tableau std :: vector> initialisé en tant que tableau [3] [1000] sera beaucoup plus petit en mémoire qu'un tableau initialisé en tant que tableau [1000] [3], et les deux seront plus grands en mémoire qu'un std: tableau alloué de toute façon.
Cela signifie également que vous ne pouvez pas simplement passer un tableau vectoriel (ou pointeur) multidimensionnel à, disons, openGL sans tenir compte de la surcharge de mémoire, mais vous pouvez naïvement passer un tableau std :: array multidimensionnel à openGL et le faire fonctionner.
la source
Un vecteur est une classe de conteneur tandis qu'un tableau est une mémoire allouée.
la source
std::vector<T>
versusT[]
, mais la question porte surstd::vector<T>
versusstd::array<T>
.