8
votes

Emplacements de pointeur de vecteur garantis?

Supposons que j'ai un vecteur d'INTS,

int *oneNumber = &numbers[43];


2 commentaires

Pour cette raison, je me méfie toujours de créer un vecteur de types de valeur, car j'ai inévitablement besoin d'un pointeur sur les objets à l'intérieur du vecteur. Donc, je sauvegarder une référence comme int * ref = & Numbers [43] .. plus tard faire quelques push_back s dans numéros et whambo! BOGUE: ref n'est pas valide, car numéros a été complètement réaffecté et enregistré dans un espace mémoire complètement différent.


@bobobobo très vrai. Bien que pour des situations où le nombre d'éléments est connu au moment de la création (et non, je ne peux pas utiliser std :: gray , car je emplace -construct les valeurs en boucle ), réserve garantit que tous les pointeurs / itérateurs dans le vecteur resteront valables, tant qu'il n'est pas redimensionné au-delà de sa capacité actuelle (ce qui pourrait forcer une réaffectation et déplacer donc les adresses des valeurs contenues) . Cela m'a sauvé quelques fois, mais chaque temps successif, j'oublie de réserve et de gratter ma tête pendant un certain temps jusqu'à ce que je me souvienne. :RÉ


7 Réponses :


2
votes

Non - le vecteur peut être réaffecté quand il s'agit. Habituellement, une fois le vecteur double de la taille.

de la norme C ++ 11 xxx


0 commentaires

8
votes

est une -enumber garanti de toujours pointer sur l'INT à l'index 43

Oui, ceci est garanti par la norme.

Même si disons que je redimensionnez des chiffres à quelque chose comme des chiffres.Resize (46)?

non. Une fois que vous avez redimensionné, ajoutez ou supprimez quoi que ce soit au vecteur, toutes les adresses et les itérateurs sont invalidés. En effet, le vecteur peut avoir besoin d'être réaffecté avec de nouveaux emplacements de mémoire.


3 commentaires

Qu'en est-il de si vous utilisez un std :: liste ? Est-ce que cela contournera le problème d'adresse non valide si vous utilisez uniquement list.push_back () appels pour ajouter des éléments? (Et vous ne retirez pas l'élément que surNumber pointe sur?


@bobobobo c'est une bonne question. Je ne suis pas sûr de ce que la norme en dit de la norme, mais je ne vois aucune raison d'ajouter / supprimer un std :: list invaliderait tous les pointeurs. (Sauf l'élément qui est supprimé) Nous en discutons dans le salon en ce moment si vous voulez vous joindre.


Trouvé une autre solution de contournement que j'utilise actuellement.



4
votes

Votre paranoïa est correcte. Redimensionner un std :: vecteur peut entraîner une modification de son emplacement de mémoire. Cela signifie que votre surNumber pointe maintenant vers un ancien emplacement de mémoire qui a été libéré, et il est donc nécessaire d'y accéder à un comportement indéfini.


0 commentaires

2
votes

Lorsque vous utilisez une fonction de redimensionnement () ou de réserve de vecteur () pour augmenter la capacité du vecteur, il peut être nécessaire de réaffecter la mémoire pour le support de réseau. Si cela réaffecte, la nouvelle mémoire ne sera pas située à la même adresse. L'adresse stockée dans Onenumber ne pointera plus au bon endroit.

Encore une fois, cela dépend du nombre d'éléments que le vecteur est actuellement utilisé pour stocker et la taille demandée. Selon les spécificités, le vecteur peut être capable de redimensionner sans réaffecter, mais vous ne devriez certainement pas supposer que ce sera le cas.


0 commentaires

4
votes

Pointeurs, références et itérateurs à STD :: Vecteur Les éléments sont garantis pour rester aussi longtemps que vous n'appuyez que sur le std :: vecteur et La taille du std :: vecteur ne se développe pas au-delà de sa capacité () au moment où le pointeur, la référence ou l'itérateur a été obtenu. Une fois qu'il est redimensionné au-delà de la capacité () Tous les pointeurs, références et itérateurs à ce std :: vecteur invalident. Notez que les choses sont également invalidées lorsque vous insérez quelque part ailleurs que la fin du std :: vecteur .

Si vous souhaitez que vos objets restent restent et que vous insérez uniquement de nouveaux éléments à la fin ou au début, vous pouvez utiliser std :: deque . Pointeurs et références aux éléments du STD :: DEQUE Obtenez uniquement invalidé lorsque vous insérez au milieu du std :: deque ou lorsque vous retirez du milieu ou lorsque vous enlevez le objet référencé. Notez que les itérateurs aux éléments du std :: deque sont invalidés chaque fois que vous insérez un élément dans le std :: deque ou retirez tout élément de celui-ci.


0 commentaires

2
votes

Une fois que vous avez changé la capacité du vecteur, les données ont été copiées sur un autre bloc de mémoire et les données d'origine sont supprimées.


0 commentaires

4
votes

Comme tous les autres ont dit, lorsque vous appelez .Resize () code> sur un vecteur, vos pointeurs deviennent invalidés car le (ancien tableau) peut être complètement traité, et un tout de nouveau neuf peut être redevable -Aluté et vos données copiées dans elle.

Une solution de contournement pour cela est ne stocke pas les pointeurs em> strong> dans un vecteur stl. Au lieu de cela, Store Integer Indices forts>. P>

Donc, dans votre exemple, P>

std::vector<int> numbers;
int *oneNumber = &numbers[43]; // no. pointers invalidated after .resize or possibly .push_back.
int oneNumberIndex = 43 ;      // yes. indices remain valid through .resize/.push_back


0 commentaires