map 中的键值都可以是啥类型的啊
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了map 中的键值都可以是啥类型的啊相关的知识,希望对你有一定的参考价值。
参考技术A map中分_KEY和——value。key的要求是重载了“<”操作符的类型。也就是说,即便是自定义的类,只要重载了<,就可以做key值。
使用 C 类型 uuid_t 作为 std::map 中的键的最佳方法是啥?
【中文标题】使用 C 类型 uuid_t 作为 std::map 中的键的最佳方法是啥?【英文标题】:what is the best way to use the C type uuid_t as a key in a std::map?使用 C 类型 uuid_t 作为 std::map 中的键的最佳方法是什么? 【发布时间】:2011-11-20 08:59:00 【问题描述】:这是在地图中提供唯一键的适当方式吗?换句话说,键是由 uuid 中包含的唯一值生成的,还是由指向 uuid_t
结构的指针生成的?一个附带的问题,当我不关心容器内的按键排序时,是否有更高效的容器?
#include <uuid/uuid.h>
int main(int argc, char **argv)
std::map<uuid_t,int> myMap;
uuid_t id1;
uuid_t id2;
uuid_generate( (unsigned char *)&id1 );
uuid_generate( (unsigned char *)&id2 );
myMap[id1] = 5;
myMap[id2] = 4;
【问题讨论】:
那你为什么需要钥匙呢?给我们更多的“背景”。为什么不vector
或简单的array
。有许多类型的容器。您是否有需要唯一 ID 的原因?
这是一个非常好的问题 Kiril,它让我思考了这个问题。我正在构建一个应用程序,它可能需要聚合由不同的、断开连接的用户创建的数据,运行不同的应用程序实例——没有可与之交谈的共享数据库。因此,使用自动递增整数进行键控是行不通的——这个想法是不要在所有传入数据源之间产生任何键冲突。我想 machine_id、时间戳和用户的一些组合也可以工作,但我真的不明白我将如何使用散列来生成唯一键。
我正在寻找一个高性能的索引,所以尽量避免使用字符串,因为我猜会是很多字符串比较。这有帮助吗?
我不确定我是否理解所有这些。你的意思是,这些用户会以某种方式被识别,并且同一个用户可能会被连接多次,而你需要将所有用户的数据存储在同一个地方?
不完全,但很接近。不同的用户可能会同时生成数据,而彼此之间没有任何联系。稍后,我需要合并记录,并促进它们之间的链接,以某种方式能够将一条记录指向另一条记录。我认为链接将包含目标记录的描述和唯一标识符(无论结果如何)。它是集体知识管理应用程序的一部分。
【参考方案1】:
我想使用第三方 C 结构的最好方法是通过它们友好的函数来使用它们。因此,如果您想在 STL 中使用 uuid_t,我建议您为该结构创建某种 C++ 接口/包装器,例如
struct Uuid
uuid_t uuid;
Uuid(const Uuid &other) uuid_copy(uuid, other.uuid);
Uuid(const uuid_t other_uuid) uuid_copy(uuid, other_uuid);
void generateInplace() uuid_generate(uuid);
static Uuid generate() Uuid wrapped; uuid_generate(wrapped.uuid); return wrapped;
bool operator<(const Uuid &other) return uuid_compare(uuid, other.uuid) < 0;
bool operator==(const Uuid &other) return uuid_compare(uuid, other.uuid) == 0;
// ...
;
这应该对您隐藏uuid_t
不是结构而是指向数组的指针(即typedef unsigned char uuid_t[16]
)这一事实。
注意:有boost version of uuid library
【讨论】:
这并不能回答您如何从uuid_t
生成唯一哈希值。
@MarkIngram, std::map
不使用哈希值。它仅使用比较运算符。如果您需要在std::unordered_map
(哈希表)中使用此类,您必须定义std::hash<uuid_t>
和std::equal_to<uuid_t>
,或者需要覆盖适当的模板参数。但这将是一个不同的问题和不同的答案。
抱歉,我自己在寻找 unordered_map 并没有发现 OP 只指定了地图。
@ony,感谢 std::hash 的附加信息,这很可能是理想的解决方案!【参考方案2】:
STL 容器始终包含对象的副本,这也适用于映射键。
支持这一点的最简单方法是使用地图的自定义比较器。
struct UUIDComparator
bool operator()(const uuid_t &a, const uuid_t &b)
//compare and return a < b
;
std::map<uuid_t, int, UUIDComparator> map;
另一个稍微有争议的解决方案是将uuid_t
转换为std::pair<uint64_t, uint64_t>
,因为这两种类型都是128 位宽,并且,AFAICT,布局兼容。 std::pair
可以直接用作地图键。
std::map<std::pair<uint64_t, uint64_t>, int, UUIDComparator> map;
【讨论】:
正如我之前提到的uuid_t
实际上是类型unsigned char[16]
。这是否意味着std::map<uuid_t, int, UUIDComparator>::key_type
将具有usigned char*
类型,并且像operator[](...)
这样的所有操作都将使用对指针的引用?
哦,我以为你说的是 uuid_t struct。如果它是一个 arrany 类型,它将不起作用,因为数组类型是不可复制的。不是,它不会衰减为指针,即用于表达式,而不是 typedef。但是如果它是一个结构体,即使里面有一个数组,它也能正常工作。
这不是我的问题,但既然有#include <uuid/uuid.h>
,我假设uuid_t
是来自libuuid 库的typedef
。在我的系统中,该库将这种类型定义为数组。关于衰减到指针 - 你是对的,但 std::pair<uuid_t, int>
的构造函数不会接受 uuid_t
作为第一个参数,我猜。【参考方案3】:
更简单:uuid_unparse(...) 将其转换为 char*(37 个字符长),然后您可以将字符串环绕...
【讨论】:
以上是关于map 中的键值都可以是啥类型的啊的主要内容,如果未能解决你的问题,请参考以下文章
java问题,我想在java中存储键值对,以便使用,但是键值对的键和值都有重复元素,使用hashmap会产生覆盖。