2010-04-02 6 views
4

dire que j'ai un objet:pointeurs vers des éléments dans un récipient

struct Foo 
{ 
    int bar_; 
    Foo(int bar) bar_(bar) {} 
}; 

et je suis un conteneur STL qui contient Foo s, peut-être un vecteur, et je prendre

// Elsewhere... 

vector<Foo> vec; 

vec.push_back(Foo(4)); 

int *p = &(vec[0].bar_) 

Ceci est un idée terrible, non? La raison est que vector va stocker ses éléments dans un tableau alloué dynamiquement quelque part, et éventuellement, si vous ajoutez suffisamment d'éléments, il devra allouer un autre tableau, copier tous les éléments du tableau original, et supprime l'ancien tableau. Après cela se produit, p points à la poubelle. C'est pourquoi de nombreuses opérations sur un vector invalideront les itérateurs.

Il semble que ce serait raisonnable de supposer qu'une opération qui invaliderait itérateurs d'un conteneur invalidera également des pointeurs vers des membres de données d'éléments de conteneurs, et que si une opération ne pas itérateurs d'invalidation, ces pointeurs toujours être en sécurité. Cependant, de nombreuses hypothèses raisonnables sont fausses. Est-ce l'un d'entre eux?

+0

@Brian: Je pense que Pillsy est correcte en sémantique, sinon en syntaxe. – quamrana

Répondre

11

La norme spécifie quand de tels pointeurs sont invalidés. Les références dans un vector meurent lorsque vous augmentez sa taille après capacity ou ajoutez/supprimez un élément précédent. Les références dans un deque sont invalidées si vous ajoutez/supprimez du milieu.

Dans le cas contraire, les références et les itérateurs peuvent être conservés pendant toute la durée de vie de l'objet sous-jacent.

+0

les références dans un 'deque' sont également invalidées lorsque vous ajoutez au milieu ... – rlbond

+0

Bonne prise. La même chose s'applique à 'vector'. – Potatoswatter

+0

'les itérateurs dans une liste peuvent être invalidés en épissant' que voulez-vous dire ici?Les itérateurs dans une liste ne sont invalidés que lorsque l'élément auquel ils se réfèrent est effacé de la liste contenant, et à ce moment précis, les références dans ces éléments sont également invalidées. Il en va de même pour l'arbre, que voulez-vous dire par «relier»? Les itérateurs dans la carte ou les ensembles sont invalidés lorsque l'élément auquel ils font référence est supprimé de la structure arborescente, tout comme les références dans ces objets. Le rééquilibrage de l'arbre n'affecte pas la validité de l'itérateur. –

1

Si le vecteur est redimensionné, le contenu sera effectivement recréé par copie et/ou affectation. Les nouveaux objets contenus seront (probablement) à des endroits différents, et donc tous les pointeurs vers le, ou vers leurs membres seront (probablement) invalidés - vous devriez certainement supposer que c'est le cas.

0

Votre hypothèse est raisonnable pour le vecteur, car un itérateur peut être implémenté comme une enveloppe fine autour d'un pointeur. Comme alternative aux pointeurs, vous pouvez stocker des décalages vers un vecteur. Ceux-ci seraient invalidés par l'insertion et l'effacement, mais pas par la réallocation de la mémoire.

1

Oui, vos instincts sont corrects. Lorsque la norme mentionne qu'un itérateur est invalidé, il tend également à indiquer que les références sont également invalidées.

Par exemple, voici un texte partiel décrivant certains des effets de la fonction membre « de réserve » de vecteur:

Notes: 
    Reallocation invalidates all the references, pointers, and iterators 
    referring to the elements in the sequence. 

Je ne peux pas imaginer toutes les fonctions de membre d'un conteneur qui invaliderait un itérateur à des éléments particuliers , mais pas de pointeurs ou de références à ces mêmes éléments, mais je suppose que je pourrais me tromper.

Il est préférable de vérifier ce que la norme indique pour votre conteneur et votre fonction de membre.

Questions connexes