惯用的;“保证唯一”;C+中的标识符+; 是否有一个习惯性的C++方法来保留和回收保证唯一的标识符?我的要求是: 假设存在当前未保留的ID,reserve\u ID(void)将返回该ID 在reserve_id()调用的连续序列中,不会两次返回单个标识符 存在一个函数recycle(id\u type),该函数将标识符返回到可用池

惯用的;“保证唯一”;C+中的标识符+; 是否有一个习惯性的C++方法来保留和回收保证唯一的标识符?我的要求是: 假设存在当前未保留的ID,reserve\u ID(void)将返回该ID 在reserve_id()调用的连续序列中,不会两次返回单个标识符 存在一个函数recycle(id\u type),该函数将标识符返回到可用池,c++,uuid,idioms,C++,Uuid,Idioms,例如,我看过,但a)我没有看到任何文档证明两个UUID的保证唯一性,b)我目前只能使用Boost的早期版本(1.40)。我可以推动升级,如果这对任务来说特别完美的话。我认为您已经通过查找Boost::Uuid解决了这个问题,但需要回收已经生成的标识符除外 根据问题的答案: 当UUID由其中一个 定义的机制,它们是 保证是独一无二的,与众不同的 从所有其他生成的UUID(即 是的,它以前从未生成过 它将永远不会再被生成), 或者它极有可能是独一无二的 (取决于机构) 如果你一心想回收和重用现有的标

例如,我看过,但a)我没有看到任何文档证明两个UUID的保证唯一性,b)我目前只能使用Boost的早期版本(1.40)。我可以推动升级,如果这对任务来说特别完美的话。

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

根据问题的答案:

当UUID由其中一个 定义的机制,它们是 保证是独一无二的,与众不同的 从所有其他生成的UUID(即 是的,它以前从未生成过 它将永远不会再被生成), 或者它极有可能是独一无二的 (取决于机构)

如果你一心想回收和重用现有的标识符,我想你可以在一段时间内建立一个UUID池,只在你需要的时候生成新的UUID,并且发现这个池是空的。但我无法想象这样的场景会比生成新的UUID更好

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

你可以这样做

  • 使用一种使获得重复UUID的机会非常遥远的技术(这就是Boost::UUID将要做的)

  • 将极有可能是唯一的UUID的生成包装到其他逻辑中,该逻辑在已生成的UUID列表中查找新生成的UUID,以消除新UUID重复的可能性。显然,当您接近列表中的大量UUID时,这样做的实用性就会降低。你预计会产生多少

  • 如果您想要大量的唯一ID,比本机类型大,那么您可以实现一个管理内存并进行必要计算的类型,然后只生成顺序ID,或者您也可以使用类似的方法来为您实现


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

      如果是前者,那么您可以只
      new
      一个字节的内存,然后使用该内存的地址作为您的标识符。这将保证是唯一的,直到您
      删除
      内存,此时它可能会被回收

      这可以很容易地包装在如下类中:

      #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;
      };
      
      #包括
      类UID
      {
      公众:
      类型定义uint64\u t id\u类型;
      静态常量id_类型保留_id()
      {
      uint8_t*idBlock=新的uint8_t;
      *idBlock=validId;
      返回(id_类型)idBlock;
      }
      静态无效回收(id\U类型id)
      {
      uint8_t*idBlock=(uint8_t*)id;
      如果(*idBlock==validId)
      {
      *idBlock=0;
      删除idBlock;
      }
      }
      私人:
      静态常数8_t validd=0x1D;
      };
      

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

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


      身份证能活多久?你真的需要回收它们吗,或者你能永远与它们共存吗?您需要一次生成多少个?你能为id投入多少比特

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

      是的,这很简单

    • reserve\u id
      功能是
      operator new(0)
    • 这将分配零字节,但具有唯一的地址
    • 回收
      功能当然是
      操作员删除

    • 您的要求不明确:按照规定,您可以使用静态id计数器
      sprintf(“id%d”,++id)
      ,它可以处理数十亿个值,或者在
      +='x'
      之后返回
      std::string
      )。如果在实践中这些价值没有耗尽,那么回收利用
      void recycle(ID) {
          container.remove(ID);
          // abort if unsuccessiful (= invalid ID)
      }
      
      ID reserve() {
          static ID last = 0;
          while(container.find(last)) {
              last++;
          }
          return last;
      }