【问题标题】:Algorithm for generating a unique ID in C++?在 C++ 中生成唯一 ID 的算法?
【发布时间】:2010-12-31 14:44:31
【问题描述】:

在 C++ 中生成唯一 ID 的最佳算法是什么? 长度 ID 应为 32 位无符号整数。

【问题讨论】:

  • 在什么意义上独一无二 - 在您的机器上,在您的应用程序中?
  • SLaks - 你怎么能在不知道他的要求的情况下这么说?从什么时候开始 GUID 是 32 位的?
  • 说实话,他们两个有什么区别?
  • 提供更多信息。 ID 的长度是 32 位整数 - 这是否意味着 40 亿位的 ID?不太可能。
  • @Ajay:至于差异 - 如果那在您的应用程序中,那么一个简单的计数器就可以完成这项工作。如果这是在机器上,那么即使在运行同一程序的不同进程之间,您也希望它是唯一的,这更加困难。

标签: c++ uniqueidentifier


【解决方案1】:

获得一个唯一的 32 位 ID 很简单:下一个。工作 40 亿次。 136 年独一无二,如果您需要一秒钟。魔鬼在细节中:前一个是什么?您需要一种可靠的方式来持久化上次使用的值,并需要一种原子方式来更新它。

具体难度取决于 ID 的范围。如果它是一个进程中的一个线程,那么您只需要一个文件。如果它是一个进程中的多个线程,那么您需要一个文件和一个互斥锁。如果一台机器上有多个进程,那么您需要一个文件和一个命名的互斥锁。如果它是多台机器上的多个进程,那么您需要分配一个权威的 ID 提供者,即所有机器都与之通信的单个服务器。数据库引擎就是这样一个常见的提供者,他们有这个内置的特性,一个自动增量列。

随着范围的扩大,获取 ID 的费用会逐渐增加。当它变得不切实际时,范围是 Internet 或提供商太慢或不可用,那么您需要放弃 32 位值。切换到随机值。随机性足以使机器被流星击中的可能性比重复相同 ID 的可能性至少高一百万倍。一个好ID。它只有 4 倍大。

【讨论】:

  • 问题概述的好答案,有没有指向最后一个解决方案的标准方法的指针,带有随机数?有什么好的实用方法可以生成足够好的随机数?
  • 也许你指的是“UUID”,正如这篇维基百科文章所描述的那样? en.wikipedia.org/wiki/…
  • 是的。一个数字是全球唯一 (guid) 还是全球唯一 (uuid) 是我不想用 10 英尺长的杆子触及的东西。这是一个大宇宙:)
【解决方案2】:

这是我能想到的最简单的 ID。

MyObject obj;
uint32_t id = reinterpret_cast<uint32_t>(&obj);

在任何给定时间,此 ID 在整个应用程序中都是唯一的。没有其他对象将位于同一地址。当然,如果您重新启动应用程序,可能会为该对象分配一个新 ID。一旦对象的生命周期结束,可能会为另一个对象分配相同的 ID。

并且不同内存空间(例如,在不同计算机上)的对象可能被分配相同的 ID。

最后但同样重要的是,如果指针大小大于 32 位,则映射将不是唯一的。

但由于我们对您想要什么样的 ID 以及它应该有多独特一无所知,所以这似乎是一个很好的答案。

【讨论】:

  • 坏主意。想象一个 64 位应用程序。该地址的 32 位很有可能是 0x00000000,或者至少对于程序中的所有对象地址都相同。 (注意:截断 reinterpret_cast 结果可能取决于字节序)
  • 我已经指出了这一点。如果指针大小大于 32 位,则会发生冲突。但由于我们对 ID 的用途或应用类型几乎一无所知,因此我只想提出简单明了的解决方案。
  • 有没有办法让这适用于 64 位和 32 位?
  • 小心这种方法。我使用了相同的方法,当您删除对象并创建新对象时,新对象可以具有相同的地址。如果你有多线程应用程序,那就太危险了。
【解决方案3】:

你可以看到this。 (我认为,完整的答案在 Stack Overflow 上。)
this site 中有关 Linux 中 C++ 中唯一 ID 的一些说明。您可以在 Linux 中使用 uuid,请参阅此人 page and sample

如果您使用 windows 并需要 windows API,请参阅此MSDN page

这个维基百科页面也很有用:http://en.wikipedia.org/wiki/Universally_Unique_Identifier

【讨论】:

    【解决方案4】:
    DWORD uid = ::GetTickCount();
    ::Sleep(100);
    

    【讨论】:

    • 对不起,理论上,如果两台机器同时执行此操作 - 两台机器将获得相同的 uid,因此该数字在计算机之间不是唯一的。请参阅尼尔对主要问题的评论。如果需求只是跨时间在同一台机器上获得唯一性,而不是跨机器唯一性,这是正确的。
    • 加上 GetTickCount() 不是很精确。您可以连续调用 3 次并得到相同的响应。
    【解决方案5】:

    如果您负担得起使用 Boost,那么有一个 UUID 库应该可以解决问题。使用起来非常简单——查看文档和this answer

    【讨论】:

      【解决方案6】:

      几乎没有上下文,但如果您正在为应用程序中的对象寻找唯一 ID,您始终可以使用类似于

      的单例方法
      class IDGenerator {
         public:
            static IDGenerator * instance ();
            uint32_t next () { return _id++; }
         private:
            IDGenerator () : _id(0) {}
      
            static IDGenerator * only_copy;
            uint32_t _id;
      }
      
      IDGenerator *
      IDGenerator::instance () {
         if (!only_copy) {
            only_copy = new IDGenerator();
         }
         return only_copy;
      }
      

      现在您可以随时通过以下方式获得唯一 ID:

      IDGenerator::instance()-&gt;next ()

      【讨论】:

      • 静态 IDGenerator &instance () { static IDGenerator Generator;返回生成器; }
      • 原始答案允许销毁单例。本地静态变量实现起来更快,但您失去了该选项。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 2012-03-21
      • 2012-07-20
      相关资源
      最近更新 更多