Les éléments std :: vector sont-ils garantis contigus?

Ma question est simple: les éléments std :: vector sont-ils garantis d’être contigus? Dans un mot d’ordre, puis-je utiliser le pointeur sur le premier élément d’un std :: vector en tant que C-array?

Si ma mémoire me sert bien, le standard C ++ n’a pas apporté 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 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' } } 

Cela a été omis du standard C ++ 98 proprement dit, mais ajouté plus tard dans le cadre d’un TR. La prochaine norme C ++ 0x contiendra bien sûr cette exigence.

De n2798 (brouillon de C ++ 0x):

23.2.6 Class template vector [vector]

1 Un vecteur est un conteneur de séquence qui prend en charge les iterators à access aléatoire. En outre, il prend en charge les opérations d’insertion et d’effacement à temps constant (amorti) à la fin; insérer et effacer au milieu prendre le temps linéaire. La gestion du stockage est gérée automatiquement, même si des conseils peuvent être donnés pour améliorer l’efficacité. Les éléments d’un vecteur sont stockés de manière contiguë, ce qui signifie que si v est un vecteur où T est un autre type que bool, alors il obéit à l’identité & v [n] == & v [0] + n pour tout 0 <= n

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 append est que si vous faites une insertion ou une suppression sur le vecteur, ce qui pourrait provoquer une réallocation de la mémoire du vecteur, vous allez invalider tous les pointeurs et les iterators enregistrés.

Le standard garantit en effet qu’un vector est continu en mémoire et que &a[0] peut être passé à une fonction C qui attend un tableau.

L’exception à cette règle est le vector qui n’utilise qu’un seul bit par bool , bien qu’il ait une mémoire continue, il ne peut pas être utilisé comme un bool* (ceci est largement considéré comme une fausse optimisation et une erreur).

BTW, pourquoi n’utilisez-vous pas les iterators? C’est pour ça qu’ils sont.

Comme d’autres l’ont déjà dit, le vector utilise en interne un tableau contigu d’objects. Les pointeurs dans ce tableau doivent être considérés comme non valides chaque fois qu’une fonction de membre non-const s’appelle IIRC.

Cependant, il existe une exception!!

vector a une implémentation spécialisée conçue pour gagner de la place, de sorte que chaque booléen utilise un seul bit. Le tableau sous-jacent n’est pas un tableau contigu de bool et l’arithmétique du tableau sur le vector ne fonctionne pas comme le ferait le vector .

(Je suppose qu’il est également possible que cela soit vrai pour n’importe quelle spécialisation de vecteur, puisque nous pouvons toujours en implémenter une nouvelle. Cependant, std::vector est la seule spécialisation standard sur laquelle l’arithmétique de pointeur simple a gagné) t travail.)

J’ai trouvé ce fil parce que j’ai un cas d’utilisation où les vecteurs utilisant une mémoire contiguë constituent un avantage.

J’apprends à utiliser des objects de tampon de vertex dans OpenGL. J’ai créé une classe wrapper pour contenir la logique du tampon, il me suffit donc de passer un tableau de flottants et quelques valeurs de configuration pour créer le tampon. Je veux pouvoir générer un tampon à partir d’une fonction en fonction de l’entrée de l’utilisateur, de sorte que la longueur n’est pas connue au moment de la compilation. Faire quelque chose comme ça serait la solution la plus simple:

 void generate(std::vector v) { float f = generate_next_float(); v.push_back(f); } 

Maintenant, je peux passer les flottants du vecteur en tant que 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 flottants et en espérant que ce soit assez grand, ou pour créer mon propre tableau dynamic avec un stockage contigu.

Oui, les éléments d’un std :: vector sont garantis contigus.

cplusplus.com:

Les conteneurs vectoriels sont implémentés en tant que tableaux dynamics. Tout comme les tableaux normaux, les conteneurs vectoriels ont leurs éléments stockés dans des emplacements de stockage contigus, ce qui signifie que leurs éléments peuvent être accédés non seulement à l’aide d’iterators mais également à des décalages sur des pointeurs réguliers vers des éléments.