C++ 中的句柄、空指针、对象

Handle , Void Pointer , Objects in C++

所以我阅读了关于 Handle in C 的文章并意识到我们将句柄实现为 void 指针,因此我们得到的“任何”Object/data 类型都可以将 void 指针转换为那种 Object/data 并得到它的值。所以我基本上有两个问题:

1.If 让我们说下面的例子取自 Handle in C

 typedef void* HANDLE;   
 int doSomething(HANDLE s, int a, int b) {
         Something* something = reinterpret_cast<Something*>(s);
         return something->doit(a, b);
     }
       

如果我们将值传递给函数dosomething(21,2,2),这是否意味着 HANDLE 指向的值是 21,如果是,那么当我们将任何对象类型转换为该对象时,它是否能够使用它,就像在这个例子中一样,所以换句话说,指向对象 Something something 的指针将存储值 21.

2.Secondly link 还说“所以在您的代码中,您只是将 HANDLE 作为不透明值传递”,这实际上是什么意思?为什么我们“传递句柄”?如果有人能给出更有说服力的使用对象的句柄示例,那就太好了!

1.:句柄是对象的标识符。由于“21”不是对象,而只是一个数字,因此您的函数调用无效。您的代码只有在“s”确实指向类型为 Something 的结构时才有效。简单地说,句柄只不过是指针,不过是内存地址,因此“21”将被解释为内存地址,如果您尝试写入它会使程序崩溃

2.: "Opaque value" 意味着使用您的代码的任何开发人员都不能对句柄标识的对象的内部结构做出任何假设。与指向结构的指针相比,这是一个优势,在结构指针中,开发人员可以查看结构并做出一些假设,这些假设在您更改代码后将不再成立。 "Pass around" 简单的意思是:赋值并作为函数调用参数使用,比如:

HANDLE s = CreateAnObject();
DoSomethingWithObject( s );
HANDLE t = s;

等等

顺便说一句:在实际代码中,您应该为对象赋予不同名称的句柄,例如 EMPLOYEE_HANDLE、ORDER_HANDLE 等。 句柄的典型示例是 Windows 中的 window 个句柄。他们识别 windows,但没有向您提供有关操作系统中 "Window" 内存结构是如何构建的任何信息,因此 Microsoft 能够更改此内部结构,而不会因更改而破坏其他开发人员的代码"Window" 结构。

If we pass the value to the function dosomething(21,2,2), does that mean the value HANDLE points to is 21,

没有。它只是意味着 void* 的值为 21。如果将 21 视为指向类型 Something 的对象的指针的值,则很可能会导致未定义的行为。

2.Secondly the link also says "So in your code you just pass HANDLE around as an opaque value" what does it actually mean? Why do we "pass handle around"? If someone can give more convincing example of handles that uses objects that will be great!

手柄是不透明的,你无法透过它看到任何东西。如果句柄由 void* 表示,您将看不到该对象的任何信息,因为 void* 无法取消引用。如果句柄由 int 表示(作为代码中其他地方定义的某个数组的索引),您无法查看句柄的值并理解相应对象表示的内容。

理解句柄的唯一方法是使用适合句柄类型的方法将其转换为指针或引用。

在句柄由 void* 表示的情况下,您发布的代码说明了如何提取指向具体对象的指针并理解该对象。

在句柄由 int 表示的情况下,您可能会看到以下内容:

int doSomething(HANDLE s, int a, int b) {

   // If the value of s is 3, something will be a reference
   // to the fourth object in the array arrayOfSomethingObjects.

   Something& something = arrayOfSomethingObjects[s];
   return something.doit(a, b);
}

我没有意识到实际上有一篇关于 HANDLE 的文章或实现它们的实际方法。它们通常是一个 windows 构造,可以以任何方式实现,某些开发人员从 1985 年开始决定实现它们。

它真的和"thingy"一样有意义,或者更确切地说"thingy that can be used to get a resource"

不要养成创建自己的 "handle" 的习惯,当然也不要尝试模仿 1985 年的代码习惯用法。空指针、reinterpret_casts 和 HANDLE 都是您应该避免的东西如果可能,不惜一切代价。

您唯一需要处理 "HANDLE" 的情况是在使用 Windows API 时,文档会告诉您如何处理它。

在现代C++中,如果你想传递对象,使用引用、指针和智能指针(包括unique_ptr、shared_ptr、weak_ptr)并研究哪个场景需要哪些。