Ma question est simple: les éléments std :: vector sont-ils garantis contigus? Dans l'ordre, puis-je utiliser le pointeur vers le premier élément d'un std :: vector comme tableau C?
Si ma mémoire est bonne, le standard C ++ ne faisait pas une telle garantie. Cependant, les exigences std :: vector étaient telles qu'il était pratiquement impossible de les satisfaire si les éléments n'étaient pas contigus.
Quelqu'un peut-il clarifier cela?
Exemple:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
values
intérieur de ceif
bloc. Cependant, je ne connais pas la réponse à votre question, alors je laisse juste un commentaire. :)values
, en particulier qui modifient sa taille (par exemple,push_back()
), peuvent provoquer une réallocation du vecteur sous-jacent qui invalide le pointeur copiéarray
. C'est le même principe que d'utiliser un vector :: iterator au lieu d'un pointeur dans le vecteur. :)Réponses:
Cela a été omis de la norme C ++ 98 proprement dite, mais ajouté plus tard dans le cadre d'un TR. Le prochain standard C ++ 0x en contiendra bien sûr une exigence.
À partir de n2798 (brouillon de C ++ 0x):
la source
std::vector
qui sont contiguës. Par exemple , .: dansstd::vector<std::vector<int>> v
les élémentsv[0]
,v[1]
... sont stockés ensuite dans la mémoire, mais l'élémentv[0].back()
etv[1].front()
ne sont pas garantis d'être.Comme d'autres réponses l'ont souligné, le contenu d'un vecteur est garanti continu (à l'exception de l'étrangeté de bool).
Le commentaire que je voulais ajouter, c'est que si vous effectuez une insertion ou une suppression sur le vecteur, ce qui pourrait provoquer la réallocation du vecteur dans sa mémoire, alors vous invaliderez tous vos pointeurs et itérateurs enregistrés.
la source
La norme garantit en fait que a
vector
est continu en mémoire et qu'il&a[0]
peut être passé à uneC
fonction qui attend un tableau.L'exception à cette règle est
vector<bool>
qu'elle n'utilise qu'un bit par bitbool
, bien qu'elle ait une mémoire continue, elle ne peut pas être utilisée comme unbool*
(ceci est largement considéré comme une fausse optimisation et une erreur).BTW, pourquoi n'utilisez-vous pas d'itérateurs? C'est à ça qu'ils servent.
la source
Comme d'autres l'ont déjà dit,
vector
utilise en interne un tableau contigu d'objets. Les pointeurs dans ce tableau doivent être traités comme non valides chaque fois qu'une fonction membre non-const est appelée IIRC.Cependant, il existe une exception!!
vector<bool>
a une implémentation spécialisée conçue pour économiser de l'espace, de sorte que chaque booléen n'utilise qu'un seul bit. Le tableau sous-jacent n'est pas un tableau contigu d'arithmétique booléenne et de tableau survector<bool>
ne fonctionne pas comme levector<T>
ferait.(Je suppose qu'il est également possible que cela soit vrai pour toute spécialisation de vecteur, puisque nous pouvons toujours en implémenter une nouvelle. Cependant,
std::vector<bool>
c'est la seule spécialisation standard erronée sur laquelle l'arithmétique de pointeur simple ne fonctionnera pas.)la source
std::vector
et tous les autres vecteurs doivent utiliser le stockage contigu. Par conséquent,std::vector<bool>
c'est (heureusement) le seul vecteur standard qui soit bizarre. (Je suis fermement d'avis que cette spécialisation devrait être déconseillée et remplacée par exemple par astd::dynamic_bitset
avec à peu près les mêmes fonctionnalités. Ce n'est pas une mauvaise structure de données, ce n'est tout simplement pas un vecteur.)J'ai trouvé ce fil parce que j'ai un cas d'utilisation où les vecteurs utilisant une mémoire contiguë sont un avantage.
J'apprends à utiliser des objets de tampon de sommet dans OpenGL. J'ai créé une classe wrapper pour contenir la logique du tampon, donc tout ce que j'ai à faire est de passer un tableau de flotteurs et quelques valeurs de configuration pour créer le tampon. Je veux pouvoir générer un tampon à partir d'une fonction basée sur l'entrée de l'utilisateur, donc la longueur n'est pas connue au moment de la compilation. Faire quelque chose comme ça serait la solution la plus simple:
Maintenant, je peux passer les flotteurs du vecteur sous forme de tableau aux fonctions liées au tampon d'OpenGL. Cela supprime également le besoin de sizeof pour déterminer la longueur du tableau.
C'est bien mieux que d'allouer un énorme tableau pour stocker les flotteurs et d'espérer que je l'ai fait assez grand, ou de créer mon propre tableau dynamique avec un stockage contigu.
la source
v
plutôt que versv
lui-même? car le passagev
seul entraînera une copie à l'intérieur de la fonction, qui cessera d'exister après la fin de la fonction. Ainsi, vous poussez quelque chose sur le vecteur uniquement pour supprimer le vecteur lorsque la fonction se termine.cplusplus.com:
la source
Oui, les éléments d'un std :: vector sont garantis contigus.
la source