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&lt;uuid_t&gt;std::equal_to&lt;uuid_t&gt;,或者需要覆盖适当的模板参数。但这将是一个不同的问题和不同的答案。 抱歉,我自己在寻找 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&lt;uint64_t, uint64_t&gt;,因为这两种类型都是128 位宽,并且,AFAICT,布局兼容。 std::pair 可以直接用作地图键。

std::map<std::pair<uint64_t, uint64_t>, int, UUIDComparator> map;

【讨论】:

正如我之前提到的uuid_t 实际上是类型unsigned char[16]。这是否意味着std::map&lt;uuid_t, int, UUIDComparator&gt;::key_type 将具有usigned char* 类型,并且像operator[](...) 这样的所有操作都将使用对指针的引用? 哦,我以为你说的是​​ uuid_t struct。如果它是一个 arrany 类型,它将不起作用,因为数组类型是不可复制的。不是,它不会衰减为指针,即用于表达式,而不是 typedef。但是如果它是一个结构体,即使里面有一个数组,它也能正常工作。 这不是我的问题,但既然有#include &lt;uuid/uuid.h&gt;,我假设uuid_t 是来自libuuid 库的typedef。在我的系统中,该库将这种类型定义为数组。关于衰减到指针 - 你是对的,但 std::pair&lt;uuid_t, int&gt; 的构造函数不会接受 uuid_t 作为第一个参数,我猜。【参考方案3】:

更简单:uuid_unparse(...) 将其转换为 char*(37 个字符长),然后您可以将字符串环绕...

【讨论】:

以上是关于map 中的键值都可以是啥类型的啊的主要内容,如果未能解决你的问题,请参考以下文章

java问题,我想在java中存储键值对,以便使用,但是键值对的键和值都有重复元素,使用hashmap会产生覆盖。

使用 C 类型 uuid_t 作为 std::map 中的键的最佳方法是啥?

Map Reduce 中的键值

scala 基础六 scala Map和元组的操作

Properties集合

Java中的集合 实现Map接口的WeakHashMap