Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 最佳实践:如何获取对象的唯一标识符_C++ - Fatal编程技术网

C++ 最佳实践:如何获取对象的唯一标识符

C++ 最佳实践:如何获取对象的唯一标识符,c++,C++,我有几个对象,需要为它们生成一个唯一的标识符,在每个对象的生命周期内不会更改/重复 基本上,我想为我的对象获取/生成一个唯一的id,如下所示 int id = reinterpret_cast<int>(&obj); 我理解上面的代码是坏主意,因为int可能不够大,无法存储地址等 那么,从对象中获取唯一标识符的最佳实践是什么,这将是一个可移植的解决方案 如果需要唯一标识对象,可以在构造函数中生成唯一id: struct Obj { int _id; Obj()

我有几个对象,需要为它们生成一个唯一的标识符,在每个对象的生命周期内不会更改/重复

基本上,我想为我的对象获取/生成一个唯一的id,如下所示

int id = reinterpret_cast<int>(&obj);
我理解上面的代码是坏主意,因为int可能不够大,无法存储地址等


那么,从对象中获取唯一标识符的最佳实践是什么,这将是一个可移植的解决方案

如果需要唯一标识对象,可以在构造函数中生成唯一id:

struct Obj
{ 
   int _id;
   Obj() { static int id = 0; _id = id++; }
};

您必须决定如何处理副本/分配(相同的id-上面的id有效/不同的id-您需要一个副本构造函数,可能需要一个
静态
类成员,而不是
静态
局部变量).

如果您的对象是一个类,那么您可以拥有一个静态成员变量,并将其设置为0。然后在构造函数中,将该值存储到类实例中,并递增静态变量:

阶级

Indexed
{
public:
   Indexed() :
       m_myIndex( m_nextIndex++ )
   { }

   int getIndex() const
   { return m_myIndex; }

private:
   const int m_myIndex;
   static int m_nextIndex;
};

当我研究这个问题时,我很快就找到了boostuuid库(通用唯一标识符,)。然而,随着项目的发展,我切换到Qt的GUID库(全局唯一标识符,)

不过,我学到的一个教训是开始声明自己的UUID类并隐藏实现,以便以后可以切换到任何适合的方式


我希望这会有所帮助。

直接使用对象地址作为唯一(用于此运行)标识符看起来不是个坏主意。为什么要将其转换为整数?只需将指针与
==
进行比较:

MyObject *obj1, *obj2;
...
if (obj1 == obj2) ...

当然,如果您需要将ID写入数据库等,这将不起作用。在两次运行之间,指针的值可能相同。另外,不要重载比较运算符(
=
)。

如果您需要分布式环境的唯一id,请根据您的“唯一性”要求使用

,有几个选项:

  • 如果在一个地址空间内(“在一个程序执行内”)是唯一的,并且对象保持在内存中的位置,那么指针就可以了。但是,也存在一些缺陷:如果对象位于容器中,每次重新分配都可能会更改对象的标识;如果允许复制对象,则从某个函数返回的对象可能是在同一地址创建的
  • 如果您需要更全局的唯一性,例如,因为您正在处理持久的程序或数据通信,请使用guid/uuid,例如
  • 您可以从一些静态计数器创建唯一的整数,但要注意以下陷阱:
    • 确保你的增量是原子的
    • 防止复制或创建自定义复制构造函数、赋值语句

就我个人而言,只要我能负担得起,我就选择UUID,因为它们让我心情轻松,不必考虑所有的陷阱。

例如,你可以使用
size\u t
,它应该和指针类型一样大。或者,如果您只需要检查相同/不同,为什么不存储指针本身呢?如果您的id不需要在程序运行或地址空间绑定中保持不变,那么地址将完成这项工作
uintpttr\u t
是足够大的整数类型。如果应用程序是多线程的,则需要同步此类型。例如,请使用类似InterlockedIncrement for Windows的内容。如果int为32位,并且您希望此进程无限期运行,则应准备处理负ID(或使其无符号)并将环绕处理回零(因此,在创建新对象/id时,必须检查对象集中的id唯一性)。哦,为了更好地衡量,我会将零设为无效句柄。
obj1==obj2
是未定义的行为。@LuchianGrigore我不知道这如何产生未定义的行为。请您详细说明一下(并提供对神圣标准的参考)?这只是一个代码片段,不是一个完成的程序。我现在添加了“…”以清楚地表明需要更多的代码行。@LuchianGrigore好的,当然,但是。。我至少认为他打算在声明和支票之间有一个
//做更多的事情…
。@LuchianGrigore,这让他更新了他的帖子,所以我想这是件好事。:)尽管在将来,如果你能从一开始就解释到底哪里错了,那可能会更有帮助如果从“变量”和“值”的角度来考虑,那么第一个项目实际上是这样说的:如果你需要变量的唯一标识符,那么没有两个变量具有相同的ID,你可以使用它们的地址;如果您需要具有值的唯一标识符,因此没有两个变量包含具有相同ID的值,那么使用变量的地址将不起作用。
MyObject *obj1, *obj2;
...
if (obj1 == obj2) ...