Ceci est inspiré par un élément de la première édition efficace C #, avertissement sur le remplacement Désolé, je n'ai pas de code de soutien. Au fait, ce n'est pas un devoir, je ne suis tout simplement pas si familier avec Supposons que je crée ma propre classe nommée personne qui a 3 champs de chaînes mutables publics: p>
Il fournit également moins que l'opérateur de comparer une personne à une autre en fonction du premier nom, puis du deuxième prénom, puis du nom de famille - c'est tout. P>
Je crée une carte de la personne à INT (dites à l'âge) et remplissez-la avec des paires de clés / valeur. Je stocke également les pointeurs vers mes clés dans un tableau. Je modifie ensuite le prénom d'un objet qui disent que le cinquième pointeur pointe et essayez de rechercher un âge correspondant en utilisant cette clé modifiée (rappelez-vous que l'objet est mutable et ouvert). P>
Pourquoi cela s'est-il arrivé? P>
a) parce que la clé utilisée par B) La collection c) quelque chose d'autre? p>
J'apprécierais vos idées. P> gethascode () code> naïvement. p>
C ++ / stl code> et n'a pas pu trouver des informations sur la mise en œuvre. P>
std :: map code> n'a pas changé (été copiée) et j'ai changé ma propre copie et ma clé n'est pas trouvée. Mais comment cela peut-il être? Je n'ai pas fourni mon propre constructeur de copie. Peut-être une valeur par défaut a été créée par le compilateur? P>
STD :: MAP CODE> est en fait un arbre noir rouge et j'ai eu un pointeur direct sur une clé. Lorsque j'ai changé la clé, je l'ai changé directement dans le nœud d'un arbre. Maintenant, il est probable que mon noeud n'est pas correctement positionné et ne sera pas trouvé à l'aide d'un algorithme de recherche d'arbres approprié. J'aurais dû supprimer le nœud, puis modifié leur clé, puis la réinsérer à nouveau. Si tel est le cas, je soupçonne que
STL CODE> Les collections en général sont plutôt dangereuses et car les noobs font de nombreuses erreurs. P>
4 Réponses :
Les entrées en font toujours une copie. Si le type de clé est (Je pense qu'il n'y a aucun moyen d'obtenir un pointeur dans les objets de la carte, vous ne pouvez donc pas changer cette clé, jamais, obtenez des copies sur l'itération ou une autre récupération.) P>
Maintenant, si votre type de clé est (et le comparateur doit être approprié pour votre type de clé.) P> std :: string code>, alors, oui, c'est une copie. (Derrière les scènes, STD :: String fait quelques optimisations afin que les personnages ne soient pas nécessairement toujours copiés, mais c'est à côté du point.) P>
* std :: string code> (un pointeur!) Ensuite, les bits du pointeur sont copiés, mais si la valeur de l'instance de chaîne donnée est modifiée ultérieurement, puis La clé sera effectivement modifiée. P>
Le conteneur standard a besoin que la classe stockée entre elles ait une valeur sémantique et donc elles sont copiées. Mais p>
Qu'est-ce que UB Royaume? Ou où est-ce?
Oui - Lorsque vous insérez un article dans une carte STD :: Plan, vous le transmettez par valeur, alors ce qu'il contient est une copie de ce que vous avez passé. Oui, le compilateur synthétisera un constructeur de copie pour vous, sauf si vous ne déclarez vous-même. P>
Il est possible de créer (par exemple) une carte qui utilise un pointeur comme clé (ainsi qu'une fonction de comparaison / fonction de fonctionnement qui compare ce que les pointeurs se rapportent). Si, toutefois, vous essayez de modifier les clés pointées par ces pointeurs, vous obtenez UB. Si vous souhaitez modifier une clé dans un ensemble / map / multiiset / multimap, vous devez supprimer l'élément existant de la collection, modifier votre copie, puis insérez la version modifiée dans la collection. P>
Lorsque vous utilisez des conteneurs STD, toutes les données sont copiées dans le conteneur. Pour les cartes, ce n'est pas différent.
Une restriction que la carte place sur les données est que la clé est non mutable. Une fois inséré, il est inséré, il est fixé pour modifier la clé, vous devez trouver / effacer et réinsérer pour modifier la valeur de la clé. P>
Person* pMap[3]; pMap[0] = &ageMap.begin().first; // Fail need a const pointer. Person const* pMapConst[3]; pMapConst[0] = &ageMap.begin().first; // OK. Note a const pointer.
Quels types de données spécifiques utilisez-vous dans votre clé? Vous dites string mais pour être clair, sont-ils STD :: Strings? Si tel est le cas, A est correct - les conteneurs stl effectueront des copies de toutes les données de la clé et de la valeur.