1

我有一个哈希映射定义为

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();
}

我的问题是,如果我必须这样做,那是修改密钥的正确方法吗?它有什么不好的副作用吗?

4

2 回答 2

3

您必须从容器中删除元素并使用新键重新添加它。

没有一个 C++ 关联容器支持以显着方式更改键(其中显着意味着更改会更改散列容器中的散列结果或有序容器中的比较)。

如果您确实修改了密钥(通过以某种方式规避 const 正确性系统),您将从查找中得到不可预测的结果。

于 2010-02-17T15:25:05.983 回答
2

您不仅不能更改密钥,因为它是 的const成员,而且您不能在不使迭代器无效的情况下pair擦除或插入成员,您拥有。当无效时,您不能增加它以从容器中获取下一个项目。hash_mapii

可能有(并且可能是)更好的算法,但我认为您需要做的是将要更改键的元素的元素(或只是键)的副本存储在其他一些临时容器中在你的for循环中。然后遍历临时容器并使用其中的信息:

  • hash_map在原始容器中获取要更改键的元素
  • erase()原始容器中的那个元素
  • insert()具有新键和原始值的新元素回到hash_map

然后你可以转储临时容器。

于 2010-02-17T16:17:48.610 回答