Quand une "clé/valeur" est inséré dans une std::map`, fait-il sa propre copie de l'objet?
Cela est inspiré par un Élément Efficace de C# de la première édition, avertissement sur la substitution GetHashCode()
naïvement.
Désolé, je n'ai pas le code de prise en charge. Par ailleurs, ce n'est pas des devoirs à faire, je ne suis pas familier avec C++/STL
, et ne pouvait pas trouver des informations concernant la mise en œuvre.
Supposons que je crée ma propre classe nom d'une personne qui a 3 public mutable champs de type chaîne:
- Prénom,
- Initiale
- Nom De Famille
Il fournit également un opérateur inférieur à comparer une personne à l'autre basé sur le prénom en premier, puis deuxième prénom, puis le nom de famille c'est tout.
J'ai créer une map à partir de la personne à int (dire l'âge), et le remplir avec quelque 20 paires clé/valeur. J'ai également stocker des pointeurs vers mes clés dans un tableau. J'ai ensuite modifier le premier nom d'un objet que dire de la cinquième pointeur de points, et essayer de trouver un correspondant de l'âge à l'aide de cette clé modifiée (rappelez-vous l'objet est mutable et grand ouvert).
Pourquoi est-ce arrivé?
A) Parce que la clé utilisée par std::map
n'a pas changé (a été copié), et j'ai changé mon propre copie et maintenant, ma clé n'est pas trouvée. Mais comment cela peut-il être? Je n'ai pas donné mon propre constructeur de copie. Peut-être un défaut a été créé par le compilateur?
B) La std::map
collection est en fait un Rouge-Noir de l'arbre, et il m'est arrivé d'avoir un pointeur direct à une touche. Quand j'ai changé la clé, je l'ai changé directement dans le nœud d'un arbre. Maintenant, il est probable que mon nœud n'est pas positionné correctement, et ne sera pas trouvée à l'aide d'un bon arbre de l'algorithme de recherche. Je devrais avoir supprimé le nœud, puis modifié, il touche, et puis re-inséré à nouveau. Si c'est le cas, alors je soupçonne que STL
collections en général sont plutôt dangereux et causer des noobs de faire beaucoup d'erreurs.
C) autre Chose?
Je vous serais reconnaissant de vos idées.
OriginalL'auteur Hamish Grubijan | 2011-04-16
Vous devez vous connecter pour publier un commentaire.
Lorsque vous utilisez std conteneurs toutes les données sont copiées dans le conteneur. Pour les cartes, ce n'est pas différent.
Une restriction que la carte des lieux sur les données est que la clé est non mutable. Une fois inséré, il est résolu de modifier la clé que vous devez trouver/effacer et insérez-la à nouveau pour changer la valeur de la clé.
Lorsque vous créez votre tableau de Personne il échouera à moins que le tableau contient des pointeurs const.
OriginalL'auteur Martin York
Le conteneur standard ont une exigence que la classe stockée en eux ont de la valeur sémantique et ainsi, ils sont copiés. Mais
OriginalL'auteur AProgrammer
Les entrées de toujours faire une copie. Si le type de clé est
std::string
, alors, oui, c'est une copie. (Derrière les scènes, std::string n'quelques optimisations, donc les personnages ne sont pas toujours copié, mais c'est à côté du sujet.)(Je pense qu'il y a pas moyen d'obtenir un pointeur sur la carte de l'objet, de sorte que vous ne pouvez pas changer cette clé, jamais encore une fois, juste obtenir des copies lors de l'itération ou d'autres de récupération.)
Maintenant, si votre type de clé est
*std::string
(un pointeur!) puis les bits du pointeur sont copiés, mais si la valeur de la chaîne de l'instance est ultérieurement modifié, alors la clé sera effectivement changé.(Et le comparateur doit être appropriée à votre type de clé.)
OriginalL'auteur david van brink
Oui -- lorsque vous insérez un élément dans une std::map, vous passer par valeur, donc ce qu'il contient est une copie de ce que vous avez passé. Oui, le compilateur va synthétiser un constructeur de copie pour vous, sauf si vous déclarez un vous-même.
Il est possible de créer (par exemple) la carte qui utilise un pointeur comme sa clé (avec une fonction de comparaison/foncteur qui compare ce que les pointeurs de référence). Si, toutefois, vous tentez de modifier les touches pointés par ces pointeurs, vous obtenez de l'UB. Si vous souhaitez modifier une clé dans un ensemble/map/multiset/multimap, vous devez supprimer l'élément existant de la collecte, de modifier votre copie, puis insérez la version modifiée de nouveau dans la collection.
OriginalL'auteur Jerry Coffin