C ++中惯用的“保证唯一”标识符

时间:2011-04-14 08:49:48

标签: c++ uuid idioms

是否有一种惯用的C ++方法来保留和回收保证唯一的标识符?我的要求是:

  1. 假设存在当前未保留的ID, reserve_id(无效)会返回该ID。
  2. 在不间断的reserve_id()调用序列中,不会返回两次单个标识符
  3. 存在一个函数 recycle(id_type),它将标识符返回给可用池。
  4. 例如,我有Boost::Uuid,但是a)我看不到哪个文档断言两个UUID的保证唯一性b)我受限于早期版本的Boost(1.40),因为暂且。如果这对于任务特别完美,我可以推动升级。

5 个答案:

答案 0 :(得分:3)

我认为你已经通过查找Boost :: Uuid解决了这个问题,除了你要求回收已经生成的标识符。

问题中的documentation you linked to

  

当UUID由其中一个生成时   定义机制,他们或者   保证是独特的,不同的   来自所有其他生成的UUID(即   是的,它从来没有生成过   并且它永远不会再生成),   或者它极有可能是独一无二的   (取决于机制)。

如果您一心想要回收并重新使用现有标识符,我想您可以维护一段时间内建立一个UUID池,只有在您需要时才会生成新UUID并发现池是空的。但是我无法想象这会产生一个新的UUID。

编辑:您评论说您需要保证唯一性。实际上,在以编程方式生成唯一标识符时,您永远不会得到一个。实际上,您将生成的ID存储在具有有限大小的数据类型中,因此您可以生成的可能ID集也是有限的。恕我直言,你能做到的最好的就是在容差阈值内模拟唯一性。

你可以通过

来做到这一点
  • 使用一种技术可以使重复的UUID非常遥远(这就是Boost :: UUID会做的事情);

  • 在一些其他逻辑中包含高度可能是唯一的UUID的生成,该逻辑在已生成的UUID列表中查找新生成的UUID,以消除新生成的UUID的微小机会是重复的。显然,当您在列表中接近大量UUID时,这样做的实用性会降低。你预计会产生多少?

  • 如果你想要真正大量的唯一ID,大于本机类型的ID,你可以实现一种管理内存并进行必要数学运算的类型,并且只生成顺序ID,或者你也许可以使用GNU Bignum Library之类的东西为你做。

答案 1 :(得分:3)

ID有多长?你真的需要回收它们,还是你可以永远与它们共存?你需要一次生成多少个?您可以将多少位用于id?

这是一个简单的方法:拿你的以太网卡的mac地址(这是全局唯一的baring硬件问题),混合时间/日期(毫秒分辨率)和递增整数计数器(每生成一个id增加一次)和你' d具有在时间/日期范围内唯一的id,只要你在这台机器上没有在一毫秒内生成它们的MAXINT。现在它不是随机的,并且攻击者可以预测它很容易,所以不要将它用于安全性,并且肯定不是最有效地使用比特,但它是全球唯一的。

答案 2 :(得分:2)

您需要什么样的独特性?
在程序的生命周期中是唯一的,还是在多次运行/跨进程中是唯一的?

如果是前者那么你只能{/ 1}}一个字节的内存然后使用该内存的地址作为你的标识符。在您new内存之前,这将保证是唯一的,此时它可以被回收。

这可以很容易地包含在这样的类中:

delete

可能有点异常,但如果您只需要每个进程的唯一性,它就符合您的要求:)

答案 3 :(得分:2)

是的,这很简单。

  1. reserve_id函数为operator new(0)
  2. 这会分配零字节,但具有唯一的地址。
  3. recycle功能当然是operator delete

答案 4 :(得分:0)

这个问题似乎与C ++没有关系,它更像是一个根本问题。在任何给定时间预计有多少ID有效?如果您希望在任何给定时间都有很少的有效ID,只需将它们放在容器中,例如链表,矢量或集合,具体取决于您的性能要求和相对回收/保留频率。排序的链表可能是最佳选择,因为您将在O(n)中同时具有循环和保留操作。向量有O(n),O(n log n)和一个集合分别有O(n log n),O(n)(可能是错误的,我的想法非常快)。

void recycle(ID) {
    container.remove(ID);
    // abort if unsuccessiful (= invalid ID)
}

ID reserve() {
    static ID last = 0;
    while(container.find(last)) {
        last++;
    }
    return last;
}