关于 std::unordered_multimap 中密钥唯一性的保证
Guarantees about key uniqueness in std::unordered_multimap
我想知道在处理迭代时 std::unordered_multimap
中关键对象的唯一性。
我将尝试解释这一点:我需要将一些数据与地图中的键类型相关联,这些数据不应在 Hash
或 KeyEqual
元素中考虑,但我需要它以避免存储单独的地图(出于优化目的)。
所以与我的想法相关的代码如下:
struct Key {
void* data;
mutable bool attribute;
Key(void* data) : data(data), attribute(false) { }
bool operator==(const Key& other) const {
return data == other.data;
}
};
struct KeyHash {
size_t operator()(const Key& key) const {
return std::hash<void*>()(key.data);
}
};
class Foo {
public:
int i;
Foo(int i) : i(i) { }
};
std::unordered_multimap<Key, Foo, KeyHash> map;
问题出在以下事实:虽然这工作正常,但无法保证作为 std::pair<const Key, Foo>
映射到单个元素的第一个元素检索到的键始终相同。作为 const Key
的 pair
听起来地图中的每个元素都有其键值副本,所以如果我这样做
void* target = new int();
map.emplace(std::make_pair(target, Foo(1)));
map.emplace(std::make_pair(target, Foo(2)));
auto pit = map.equal_range(target);
pit.first->first.attribute = true;
std::cout << std::boolalpha << (++pit.first)->first.attribute << endl;
这会产生 false
,这证实了我的想法。因此,如果您有多个具有相同键的值(这是您想要的,因为您使用的是 std::unordered_map
),确实有很多 space 被浪费在存储键上。
除了
之外,我没有看到任何其他解决方案
struct Value
{
std::vector<Foo> foos;
bool attribute;
};
std::unordered_map<void*, Value> map;
这允许我将属性与键配对,但由于它需要使用两级迭代器,所以一切都不太干净。
还有其他我没有看到的解决方案吗?
23.5.5.1 Class template unordered_multimap overview [unord.multimap.overview]
1 An unordered_multimap is an unordered associative container that supports equivalent keys (an instance of
unordered_multimap may contain multiple copies of each key value) and that associates values of another
type mapped_type with the keys. The unordered_multimap class supports forward iterators.
一个 unordered_multimap
可能包含多个密钥副本,如果您想要一个密钥副本,那么 unordered_map<K, vector<V>>
可能更合适。
我想知道在处理迭代时 std::unordered_multimap
中关键对象的唯一性。
我将尝试解释这一点:我需要将一些数据与地图中的键类型相关联,这些数据不应在 Hash
或 KeyEqual
元素中考虑,但我需要它以避免存储单独的地图(出于优化目的)。
所以与我的想法相关的代码如下:
struct Key {
void* data;
mutable bool attribute;
Key(void* data) : data(data), attribute(false) { }
bool operator==(const Key& other) const {
return data == other.data;
}
};
struct KeyHash {
size_t operator()(const Key& key) const {
return std::hash<void*>()(key.data);
}
};
class Foo {
public:
int i;
Foo(int i) : i(i) { }
};
std::unordered_multimap<Key, Foo, KeyHash> map;
问题出在以下事实:虽然这工作正常,但无法保证作为 std::pair<const Key, Foo>
映射到单个元素的第一个元素检索到的键始终相同。作为 const Key
的 pair
听起来地图中的每个元素都有其键值副本,所以如果我这样做
void* target = new int();
map.emplace(std::make_pair(target, Foo(1)));
map.emplace(std::make_pair(target, Foo(2)));
auto pit = map.equal_range(target);
pit.first->first.attribute = true;
std::cout << std::boolalpha << (++pit.first)->first.attribute << endl;
这会产生 false
,这证实了我的想法。因此,如果您有多个具有相同键的值(这是您想要的,因为您使用的是 std::unordered_map
),确实有很多 space 被浪费在存储键上。
除了
之外,我没有看到任何其他解决方案struct Value
{
std::vector<Foo> foos;
bool attribute;
};
std::unordered_map<void*, Value> map;
这允许我将属性与键配对,但由于它需要使用两级迭代器,所以一切都不太干净。
还有其他我没有看到的解决方案吗?
23.5.5.1 Class template unordered_multimap overview [unord.multimap.overview]
1 An unordered_multimap is an unordered associative container that supports equivalent keys (an instance of unordered_multimap may contain multiple copies of each key value) and that associates values of another type mapped_type with the keys. The unordered_multimap class supports forward iterators.
一个 unordered_multimap
可能包含多个密钥副本,如果您想要一个密钥副本,那么 unordered_map<K, vector<V>>
可能更合适。