stl hash_map - модифицирующий ключ - PullRequest
1 голос
/ 17 февраля 2010

У меня есть хеш-карта, определенная как

class KeyType {
    int key;
    mutable bool flag;
    KeyType(int key) : key(key), flag(false) {}
    void setFlag() const { flag = true; }
};

struct KeyType_hasher {
    size_t operator()(const KeyType& s) const {
        return static_cast<size_t> key;
    }
};

struct KeyType_equal {
    size_t operator()(const KeyType& s1, const KeyType& s2) const {
        return s1.key == s2.key;
    }
};

typedef hash_map<KeyType , ValueType, KeyType_hasher, KeyType_equal > KeyValueMap;

Позже в коде у меня есть место, где я должен выполнить цикл по карте и применить функцию к каждому найденному значению.Исходя из результата работы функции, я должен также изменить ключ на итераторе.

KeyValueMap theMap;
// theMap[key1] = value1;
// theMap[key2] = value2;
// theMap[key3] = value3;
for(KeyValueMap::iterator i = theMap.begin(); i != theMap.end(); ++i) {
    if(true == ValueFunction(i->second))
        i->first.setFlag();
}

Мой вопрос: будет ли это правильным способом изменения ключа, если потребуется?Есть ли у него плохие побочные эффекты?

Ответы [ 2 ]

3 голосов
/ 17 февраля 2010

Вам нужно будет удалить элемент из контейнера и повторно добавить его с новым ключом.

Ни один из ассоциативных контейнеров C ++ не поддерживает значительное изменение ключа (где значительный означает, что изменение изменяет результаты хеширования в хешированном контейнере или сравнения в упорядоченном контейнере).

Если вы измените ключ (обойдя систему корректности констант), вы получите непредсказуемые результаты поиска.

2 голосов
/ 17 февраля 2010

Мало того, что вы не можете изменить ключ, поскольку он является const членом pair, вы не можете удалить или вставить элементы в hash_map без аннулирования итератора, i, который у вас есть. Когда i признан недействительным, вы не можете увеличить его, чтобы получить следующий элемент из контейнера.

Может быть (и, вероятно, есть) лучший алгоритм, но я думаю, что вам нужно будет сохранить копии элементов (или только ключей) элементов, для которых вы хотите изменить ключи в некоторых другой временный контейнер в вашем for цикле. Затем пройдитесь по временному контейнеру и используйте информацию в нем:

  • получить элемент, для которого вы хотите изменить ключ, в исходном hash_map контейнере
  • erase() этот элемент из исходного контейнера
  • insert() новый элемент с новым ключом и исходным значением обратно в hash_map

Затем вы можете сбросить временный контейнер.

...