![](/img/trans.png)
[英]C++: Alternative to std::map when all entries guaranteed to be unique
[英]Idiomatic “guaranteed-unique” identifiers in C++
是否有一种惯用的C ++方法来保留和回收保证唯一的标识符? 我的要求是:
例如,我看过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;
};
可能有点不寻常 ,但如果您只需要每个进程的唯一性,它就符合您的要求:)
是的,这很简单。
reserve_id
函数是operator new(0)
。 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.