tags:

views:

609

answers:

3

I'm trying to insert some value pairs into a std::map. In the first case, I receive a pointer to the map, dereference it and use the subscript operator to assign a value. i.e.

(*foo)[index] = bar;

Later, when I try to iterate over the collection, I'm returned key/value pairs which contain null for the value attribute in all cases except for the first (map.begin()) item. The weird thing is, if I do the insertion via the map's insert function, everything is well, i.e:

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

Why would this be? Aren't the two methods functionally equivalent? I've pasted some snippets of actual code below for context

...
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++;
    }

}

I'm all out of ideas. Does anyone have a suggestion please?

+2  A: 

Does your value type have an assignment operator?

Take a look at this reference. The [] operator returns a non-const reference to the value. If your assignment is wrong or somehow works in an unexpected way this might be the cause.

The insert method on the other hand takes a value and stuffs it into the map. The [] operator constructs an object with the default constructor, then let's you assign stuff to it using it's assignment operator.

Skurmedel
Pointers are assignable.
tstenner
+3  A: 

You should be aware that operator[] for std::map will insert a value into the map if one does not exist when used in expressions like this:

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

If the value x does not exist, one will be created and assigned the value created by the value types default constructor, or zero for the built-in types. This is almost never what you want, and you should generally avoid the use of operator[] with maps.

anon
+9  A: 

In your actual code you have:

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

This will not assign tmp into the map, but will instead reference into the map creating an empty value (see @Neil Butterworth) - you have == instead of =. What you want is:

(*cycleNodes)[tmp->getId()] = tmp;
Simon Steele
I was aware of the other behaviour of operator[] but I can't believe that I missed using "==" instead of "="! Thank you Simon.
Daniel
Thank you also to everyone else for your kind input.
Daniel
Can't count how many times I've made the same mistake - it's normally easier to spot!
Simon Steele