繁体   English   中英

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

[英]Idiomatic “guaranteed-unique” identifiers in C++

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

  1. 假设存在当前未保留的ID,则reserve_id(void)返回该ID。
  2. 在不间断的reserve_id()调用序列中, 不会返回两次单个标识符
  3. 存在一个函数recycle(id_type) ,它将标识符返回给可用池。

例如,我看过Boost :: Uuid ,但是a)我看不到哪个文档断言两个UUID的保证唯一性b)我暂时只限于早期版本的Boost(1.40)。 如果这对于任务特别完美,我可以推动升级。

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

在问题中链接到文档

当UUID由其中一个定义的机制生成时,它们要么保证是唯一的,要么与所有其他生成的UUID不同(也就是说,它之前从未生成过,它永远不会再生成),或者极有可能是独一无二的(取决于机制)。

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

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

你可以这样做

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

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

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

身份证有多长? 你真的需要回收它们,还是你可以永远与它们共存? 你需要一次生成多少个? 你可以将多少比特用于身份证?

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

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

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

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

#include <stdint.h>

class UID
{
public:
        typedef uint64_t id_type;

        static const id_type reserve_id()
        {
                uint8_t* idBlock = new uint8_t;
                *idBlock = validId;
                return (id_type)idBlock;
        }

        static void recycle(id_type id)
        {
                uint8_t* idBlock = (uint8_t*)id;
                if (*idBlock == validId)
                {
                        *idBlock = 0;
                        delete idBlock;
                }
        }
private:
        static const uint8_t validId = 0x1D;
};

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

是的,这很简单。

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

这个问题似乎与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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM