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

     2023-02-22     47

关键词:

【中文标题】使用 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 个字符长),然后您可以将字符串环绕...

【讨论】:

如何使用 Python C/C++ 接口将实例成员函数作为 PyCFunction 类型传递

】如何使用PythonC/C++接口将实例成员函数作为PyCFunction类型传递【英文标题】:HowdoIpassainstancememberfunctionasaPyCFunctiontypeusingthePythonC/C++Interface【发布时间】:2014-04-0417:51:33【问题描述】:我正在尝试将python嵌入到现有的C++应用程序... 查看详情

我可以在 C++ Actor Framework 中使用 C++11 智能指针作为消息返回类型吗?

】我可以在C++ActorFramework中使用C++11智能指针作为消息返回类型吗?【英文标题】:CanIuseC++11smartpointersasamessagereturntypeintheC++ActorFramework?【发布时间】:2015-11-1021:44:21【问题描述】:当我使用unique_ptr作为返回类型时,我收到编译... 查看详情

使用自定义类类型作为键的 C++ unordered_map

】使用自定义类类型作为键的C++unordered_map【英文标题】:C++unordered_mapusingacustomclasstypeasthekey【发布时间】:2013-06-1002:34:40【问题描述】:我正在尝试使用自定义类作为unordered_map的键,如下所示:#include<iostream>#include<algorit... 查看详情

使用自定义类类型作为键的 C++ unordered_map

】使用自定义类类型作为键的C++unordered_map【英文标题】:C++unordered_mapusingacustomclasstypeasthekey【发布时间】:2013-06-1002:34:40【问题描述】:我正在尝试使用自定义类作为unordered_map的键,如下所示:#include<iostream>#include<algorit... 查看详情

使用自定义类类型作为键的 C++ unordered_map

】使用自定义类类型作为键的C++unordered_map【英文标题】:C++unordered_mapusingacustomclasstypeasthekey【发布时间】:2013-06-1002:34:40【问题描述】:我正在尝试使用自定义类作为unordered_map的键,如下所示:#include<iostream>#include<algorit... 查看详情

使用自定义类类型作为键的 C++ unordered_map

】使用自定义类类型作为键的C++unordered_map【英文标题】:C++unordered_mapusingacustomclasstypeasthekey【发布时间】:2013-06-0515:41:40【问题描述】:我正在尝试使用自定义类作为unordered_map的键,如下所示:#include<iostream>#include<algorit... 查看详情

使用自定义类类型作为键的 C++ unordered_map

】使用自定义类类型作为键的C++unordered_map【英文标题】:C++unordered_mapusingacustomclasstypeasthekey【发布时间】:2013-06-1002:34:40【问题描述】:我正在尝试使用自定义类作为unordered_map的键,如下所示:#include<iostream>#include<algorit... 查看详情

使用 `size_t` 作为计数器的类型

】使用`size_t`作为计数器的类型【英文标题】:Use`size_t`asthetypeforacounter【发布时间】:2014-09-2314:15:24【问题描述】:使用size_t代替int或unsigned作为计数器的类型是否合适?以下代码摘自C++Primer。size_tcount_calls()staticsize_tctr=0;return++c... 查看详情

在 C# 中使用枚举作为泛型类型参数 [重复]

】在C#中使用枚举作为泛型类型参数[重复]【英文标题】:UsingenumasgenerictypeparameterinC#[duplicate]【发布时间】:2011-06-2210:27:37【问题描述】:可能重复:EnumtypeconstraintsinC#是否可以通过使用其包装类Enum将enum类型用作泛型参数?我有... 查看详情

C++ 无法使用 vector<string> 作为返回类型

】C++无法使用vector<string>作为返回类型【英文标题】:C++Unabletousevector<string>asreturntype【发布时间】:2012-03-0920:36:33【问题描述】:我正在尝试使用建议的函数here通过分隔符拆分字符串,但每当我尝试使用vector&lt;string... 查看详情

c++ 使用友好类的类型作为模板参数声明 stl 向量

】c++使用友好类的类型作为模板参数声明stl向量【英文标题】:c++declaringstlvectorusingtypeofbefriendingclassastemplateargument【发布时间】:2012-10-1502:02:35【问题描述】:我有以下代码:template<typenameT>classAfriendclassB;structmodel_struct[...]te... 查看详情

使用 C++ 类成员函数作为 C 回调函数

】使用C++类成员函数作为C回调函数【英文标题】:UsingaC++classmemberfunctionasaCcallbackfunction【发布时间】:2010-11-0307:03:09【问题描述】:我有一个C库,需要注册一个回调函数来自定义一些处理。回调函数类型为inta(int*,int*)。我正在... 查看详情

如何使用 C++ 成员函数作为 C 框架的回调函数

】如何使用C++成员函数作为C框架的回调函数【英文标题】:HowtouseaC++memberfunctionasthecallbackfunctionforaCframework【发布时间】:2011-07-1915:20:18【问题描述】:有一个支持回调函数类型的C库(我无法更改)void(*callback)(void*appContext,inteven... 查看详情

使用 Atmel Studio 作为通用 C 编译器

】使用AtmelStudio作为通用C编译器【英文标题】:UseAtmelStudioasGeneralCCompiler【发布时间】:2015-01-2821:30:24【问题描述】:我正在尝试深入学习C。我的最终目标是更深入地研究AVR编程和硬件,因此我下载了AtmelStudio。我正在阅读一本C... 查看详情

使用对象类型作为方法的参数和作为方法的返回值

使用对象类型作为方法的参数使用对象类型作为方法的返回值 查看详情

我啥时候应该使用 std::string / std::string_view 作为参数/返回类型

】我啥时候应该使用std::string/std::string_view作为参数/返回类型【英文标题】:WhenshouldIusestd::string/std::string_viewforparameter/returntype我什么时候应该使用std::string/std::string_view作为参数/返回类型【发布时间】:2019-06-1812:11:47【问题描述... 查看详情

c语言-指针作为函数形参类型(代码片段)

...的参数和返回值几乎都是指针类型。这篇文章就介绍如何使用指针作为函数参数、并且使用指针作为函数返回值。下面通过几个示例代码来演示用法。2.通过指针间接修改主函数里局部变量空间的值#include<stdio.h>#include<strin... 查看详情

c++lambda表达式作为参数(代码片段)

Lambda表达式又称为小型函数,它的使用方法是:[捕获方式](参数类型)->返回类型代码通常我们不会写返回类型,因为编译器可以根据Return语句来推导返回类型,隐式为我们去加上去。相关可以参考:C/C+... 查看详情