Странная ошибка при вставке в C ++ std :: map - PullRequest
1 голос
/ 27 апреля 2009

Я пытаюсь вставить несколько пар значений в std :: map. В первом случае я получаю указатель на карту, разыменую его и использую оператор индекса, чтобы присвоить значение. т.е.

(*foo)[index] = bar;

Позже, когда я пытаюсь перебрать коллекцию, мне возвращаются пары ключ / значение, которые содержат ноль для атрибута значения во всех случаях, кроме первого (map.begin ()) элемента. Странная вещь, если я делаю вставку через функцию вставки карты, все хорошо, т.е.:

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

С чего бы это? Разве два метода не являются функционально эквивалентными? Я вставил некоторые фрагменты кода ниже для контекста

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

}

У меня нет идей. У кого-нибудь есть предложения, пожалуйста?

Ответы [ 3 ]

12 голосов
/ 27 апреля 2009

В вашем текущем коде у вас есть:

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

Это не назначит tmp на карту, но вместо этого будет ссылаться на карту, создавая пустое значение (см. @Neil Butterworth) - у вас = = вместо =. То, что вы хотите:

(*cycleNodes)[tmp->getId()] = tmp;
4 голосов
/ 27 апреля 2009

Вы должны знать, что оператор [] для std :: map вставит значение в карту, если оно не существует, когда используется в выражениях, подобных этому:

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

Если значение x не существует, оно будет создано и ему будет присвоено значение, созданное конструктором по умолчанию для типов значений, или ноль для встроенных типов. Это почти никогда не то, что вам нужно, и вам, как правило, следует избегать использования оператора [] с картами.

2 голосов
/ 27 апреля 2009

У вашего типа значения есть оператор присваивания?

Взгляните на эту ссылку . Оператор [] возвращает неконстантную ссылку на значение. Если ваше назначение неверно или каким-то образом работает неожиданным образом, это может быть причиной.

Метод вставки, с другой стороны, берет значение и вставляет его в карту. Оператор [] создает объект с помощью конструктора по умолчанию, а затем позволяет назначить ему объект с помощью оператора присваивания.

...