2009-04-27 6 views
1

J'essaie d'insérer des paires de valeurs dans une carte std :: map. Dans le premier cas, je reçois un pointeur sur la carte, je le déréférence et j'utilise l'opérateur d'indice pour attribuer une valeur. à savoirBogue bizarre lors de l'insertion dans C++ std :: map

(*foo)[index] = bar; 

Plus tard, lorsque je tente de parcourir la collection, je rentrai paires clé/valeur qui contiennent NULL pour l'attribut de valeur dans tous les cas, sauf pour la première (map.begin()) élément. La chose étrange est, si je fais l'insertion via la fonction d'insertion de la carte, tout est bien, i.e.:

foo->insert(std::pair<KeyType,ValueType>(myKey, myValue)); 

Pourquoi serait-ce? Les deux méthodes ne sont-elles pas fonctionnellement équivalentes? J'ai collé quelques extraits de code réel ci-dessous pour le contexte

... 
typedef std::map<int, SCNode*> SCNodeMap; 
... 


void StemAndCycle::getCycleNodes(SCNodeMap* cycleNodes) 
{ 
    (*cycleNodes)[root->getId()] = root; 

    SCNode* tmp = root->getSucc(); 
    while(tmp->getId() != root->getId()) 
    { 
     // (*cycleNodes)[tmp->getId()] == tmp; // crashes (in loop below) 
     cycleNodes->insert(std::pair<int, SCNode*>(tmp->getId(), tmp));//OK 
     std::pair<int, SCNode*> it = *(cycleNodes->find(tmp->getId())); 
     tmp = tmp->getSucc(); 
    } 

    // debugging; print ids of all the SCNode objects in the collection 
    std::map<int, SCNode*>::iterator it = cycleNodes->begin(); 
    while(it != cycleNodes->end()) 
    { 
     std::pair<int, SCNode*> p = (*it); 
     SCNode* tmp = (*it).second; // null except for it = cycleNodes->begin() 
     std::cout << "tmp node id: "<<tmp->getId()<<std::endl; 
     it++; 
    } 

} 

Je suis à court d'idées. Est-ce que quelqu'un a une suggestion s'il vous plaît?

+0

Quel type est racine? – Skurmedel

Répondre

12

Dans votre code réel que vous avez:

(*cycleNodes)[tmp->getId()] == tmp; 

Cela ne peut céder tmp dans la carte, mais au lieu de référence dans la carte créer une valeur vide (voir @Neil Butterworth) - vous avez == au lieu de =. Ce que vous voulez est:

(*cycleNodes)[tmp->getId()] = tmp; 
+0

J'étais conscient de l'autre comportement de l'opérateur [] mais je n'arrive pas à croire que j'ai manqué d'utiliser "==" au lieu de "="! Merci Simon. – Daniel

+0

Merci également à tous les autres pour votre aimable contribution. – Daniel

+0

Je ne peux pas compter combien de fois j'ai fait la même erreur - c'est normalement plus facile à repérer! –

2

Votre type de valeur a-t-il un opérateur d'affectation?

Jetez un oeil à this reference. L'opérateur [] renvoie une référence non-const à la valeur. Si votre mission est mauvaise ou fonctionne d'une manière inattendue, cela pourrait être la cause.

La méthode insert, quant à elle, prend une valeur et l'insère dans la carte. L'opérateur [] construit un objet avec le constructeur par défaut, puis vous lui assigner des choses en utilisant son opérateur d'affectation.

+0

Les pointeurs sont assignables. – tstenner

4

Vous devez savoir que l'opérateur [] pour std :: carte insère une valeur dans la carte si l'on n'existe pas lorsqu'il est utilisé dans des expressions comme ceci:

if (amap[x] == 42) { 
    ... 
} 

Si la valeur x n'existe pas , un sera créé et assigné la valeur créée par le constructeur par défaut des types de valeur, ou zéro pour les types intégrés. Ce n'est presque jamais ce que vous voulez, et vous devriez généralement éviter l'utilisation de l'opérateur [] avec des cartes.

+0

Merci! Je viens de perdre une demi-journée à cette idiotie. –