Est-il prudent de supposer que le stockage vectoriel STL est toujours contigu?
Question
Si vous avez un vecteur STL redimensionné, est-il prudent de prendre l'adresse de l'élément 0 et de supposer que le reste du vecteur suivra en mémoire?
par exemple
vector<char> vc(100);
// do some stuff with vc
vc.resize(200);
char* p = &vc[0];
// do stuff with *p
La solution
Oui, cette hypothèse est valide (*).
À partir du standard C ++ 03 (23.2.4.1):
Les éléments d'un vecteur sont stockés contiguë, ce qui signifie que si v est un vecteur où T est un peu tapez autre chose que bool, alors il obéit l'identité & amp; v [n] == & amp; v [0] + n pour all 0 < = n < v.size ().
(*) ... mais faites attention à la réallocation du tableau (en invalidant les pointeurs et les itérateurs) après l'ajout d'éléments.
Autres conseils
La formulation standard C ++ 03 a été ajoutée pour préciser que les éléments vectoriels doivent être contigus.
C ++ 03 23.2.4 Le paragraphe 1 contient le langage suivant, qui est pas dans le document standard C ++ 98:
Les éléments d'un
vector
sont stockés contiguë, ce qui signifie que siv
est unvector<T, Allocator>
oùT
est un autre type quebool
, alors il obéit à l'identité&v[n] == &v[0] + n
pour tous0 <= n < v.size()
.
Herb Sutter parle de ce changement dans l'une de ses entrées de blog, Ne cringe pas: les vecteurs sont garantis contigus :
... la contiguïté fait en fait partie de la abstraction de vecteur. C’est si important! en fait, quand il a été découvert que la norme C ++ 98 n'a pas & # 8217; t garantir complètement la contiguïté, le La norme C ++ 03 a été modifiée pour ajouter explicitement la garantie.
Le stockage est toujours contigu, mais il peut se déplacer si la capacité du vecteur est modifiée.
Si vous aviez un pointeur, une référence ou un itérateur sur l'élément zéro (ou sur un élément) avant une opération de modification de capacité, il est invalidé et doit être réaffecté.
std::vector
garantit que les éléments sont stockés dans un tableau contigu et constitue par conséquent le remplacement préféré des tableaux. Il peut également être utilisé pour l'interface avec du code de bas niveau dépendant de la plate-forme (comme les appels Win32 API). Pour obtenir un pointeur sur le tableau, utilisez:
&myVector.front();
oui.
il devrait toujours être contigu