Les éléments vectoriels std::sont-ils contigus?

ma question est simple: les éléments vectoriels std::sont-ils sûrs d'être contigus? Dans word, puis-je utiliser le pointeur vers le premier élément d'un std::vector comme un C-ensemble?

si ma mémoire me sert bien, le standard C++ n'a pas fait une telle garantie. Cependant, le std::vector conditions étaient telles qu'il était pratiquement impossible de les rencontrer si ces éléments n'étaient pas contiguës.

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'
    }
}
86
demandé sur Rob Kennedy 2009-05-11 21:38:05

7 réponses

cela a été omis de C++98 standard proper mais ajouté plus tard dans le cadre d'un TR. La prochaine norme C++0x contiendra bien sûr cette exigence.

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

23.2.6 classe modèle de vecteur [Vecteur]

1 un vecteur est un conteneur séquentiel qui supporte des itérateurs d'accès aléatoires. En outre, il prend en charge (amorti) constante de temps d'insertion et de les opérations d'effacement à la fin; insérer et effacer au milieu prennent du temps linéaire. Stockage la gestion est gérée automatiquement, bien que des conseils puissent être donnés pour améliorer l'efficacité. Les éléments d'une les vecteurs sont stockés en contiguïté, 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 TOUS 0 < = n < V. size().

88
répondu dirkgently 2009-05-11 17:42:47

comme d'autres réponses l'ont fait remarquer, le contenu d'un vecteur est assuré d'être continu (à l'exception de la bizarrerie de bool).

le commentaire que je voulais ajouter, c'est que si vous faites une insertion ou une suppression sur le vecteur, ce qui pourrait amener le vecteur à réattribuer sa mémoire, alors vous allez faire invalider tous vos pointeurs et itérateurs enregistrés.

14
répondu Bill Lynch 2013-08-31 07:05:07

la norme 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 vector<bool> qui n'utilise qu'un bit par bool ainsi, 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 ne pas utiliser les itérateurs? C'est ce qu'ils sont pour.

6
répondu Motti 2009-05-11 17:47:17

comme d'autres l'ont déjà dit, vector utilise en interne un réseau contigu d'objets. Les pointeurs dans ce tableau devraient être traités comme invalides chaque fois qu'une fonction de membre non-const est appelée IIRC.

cependant, il y a une exception!!

vector<bool> dispose d'une implémentation spécialisée conçue pour économiser de l'espace, de sorte que chaque bool n'utilise qu'un bit. Le tableau sous-jacent n'est pas un tableau contigu de bool et de tableau arithmétique sur vector<bool> ne marche pas comme vector<T> le ferait.

(je suppose qu'il est aussi possible que cela soit vrai de n'importe quelle spécialisation de vecteur, puisque nous pouvons toujours mettre en œuvre un nouveau. Cependant, std::vector<bool> est la seule, erreur, la spécialisation standard sur laquelle l'arithmétique simple pointeur ne fonctionnera pas.)

5
répondu Wuggy 2009-05-12 03:23:10

j'ai trouvé ce fil parce que j'ai un cas d'utilisation où les vecteurs utilisant la mémoire contiguë est un avantage.

j'apprends à utiliser les objets tampons vertex dans OpenGL. J'ai créé une classe wrapper pour contenir la logique du buffer, donc tout ce que je dois faire c'est passer un tableau de flotteurs et quelques valeurs de configuration pour créer le buffer. Je veux être capable de générer un tampon à partir d'une fonction basée sur les entrées 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 facile:

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

maintenant je peux passer les flotteurs du vecteur comme un tableau aux fonctions liées au tampon D'OpenGL. Cela supprime également la nécessité pour sizeof pour déterminer la longueur du tableau.

c'est beaucoup mieux que d'allouer un réseau énorme pour stocker les flotteurs et espérer que je l'ai fait assez grand, ou faire mon propre réseau dynamique avec un stockage contigu.

3
répondu NobodyImportant 2012-12-08 19:52:12

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

2
répondu Benoît 2009-05-11 18:23:56

cplusplus.com:

les conteneurs vectoriels sont mis en œuvre en tant que tableaux dynamiques; tout comme les tableaux réguliers, les conteneurs vectoriels ont leurs éléments stockés dans des emplacements de stockage contigus, ce qui signifie que leurs éléments peuvent être accessibles non seulement en utilisant des itérateurs, mais aussi en utilisant des offsets sur des pointeurs réguliers vers les éléments.

1
répondu Igor Oks 2009-05-11 17:41:47