为什么它在这里使用void **?

时间:2017-01-07 12:42:47

标签: c++ v8 reinterpret-cast

代码从v8-0.2.5

获取
/**
 * Checks whether two handles are the same.
 * Returns true if both are empty, or if the objects
 * to which they refer are identical.
 * The handles' references are not checked.
 */
template <class S> bool operator==(Handle<S> that) {
  void** a = reinterpret_cast<void**>(**this);
  void** b = reinterpret_cast<void**>(*that);
  if (a == 0) return b == 0;
  if (b == 0) return false;
  return *a == *b;
}  

Handle重载运算符*,以便**this*that返回T*类型。

所以看来

  void* a = reinterpret_cast<void*>(**this);
  void* b = reinterpret_cast<void*>(*that);
  return a == b;

也会运作良好吗?

3 个答案:

答案 0 :(得分:2)

如果ab的类型为void*,那么您无法取消引用它们(不先将它们转换为其他内容),因此*a == *b无效

答案 1 :(得分:2)

首先,我发现我只是在对角线上阅读链接中的代码。显然,Handle类重载了解除引用操作符(*)以返回正在处理的T*。因此,第一行中的表达式表示以下内容:

  • this是一个(可能是cv资格的)Handle<T> * const
  • *thisHandle<T> &
  • **this是句柄operator*的返回值,即您提到的T*
  • 最后,T*被重新解释为void**。请注意,添加了一个额外的间接,因此可以取消引用结果,并生成void* &而不是T&
  • that的等效行产生的S*被重新解释为void**

因此,您会得到一些指向不同类型T*S*的指针,它们会被神奇地重新解释为void**。然后代码执行空检查和然后,神奇的行:

return *a == *b;

比较实际的sizeof(void*)T类型对象的(可能未对齐!)第一个S字节 em> ab指向的。除非您完全确定TS具有适当的大小和对齐方式,否则检查完全是假的。 例如,如果你知道T本身总是指针或指针大小相同的智能指针对象,那么检查就有意义了,所以你可能有不同的句柄指向不同的指针对象仍然指向(在第二个间接级别)同一个对象。这允许GC通过简单地更新第一级指针的内容来移动底层对象而不必更新它的所有句柄。

Handle<T> has T* -----> T = U* pinned in memory -----> actual object U can be moved

所以,为了回答你的问题,仅投射到void*(不增加间接)与在代码中进行检查不一样 - 你的版本会比较指针,所以在我的例子中,同一个对象的两个不同句柄可能与你的备用代码不相等。

PS:让你的班级从T*operator*返回operator->也是不好的风格,因为那样你就会打破p->x(*p).x之间的一般身份{1}}。如果成员访问运算符返回T&,则解引用运算符通常应返回T*

答案 2 :(得分:0)

Javier Martín是对的。当你有问题时,你不能仅仅比较指针。首先,在上下文ov v8中,Handle<T>对类型T有限制。你不能参加任何课程并将Handle应用于它。 T只是用户处理的外观类:v8::Stringv8::Integer等等。永远不会创建此类类型的对象,但这些类用作内部接口。

实际上,Handle<>存储的指针是一个指针,指示&#34; Tag&#34;。我们有两个Handle<>引用相同的对象,如果它们的标签相同。内部标记的大小为void*,并以某种方式指向真实对象。用户不需要知道标记是什么,Handle<>使用void*代替。一些想法

  1. Handle<T>T* - &gt;标记(不是T) - (某种程度上) - &gt;真实对象(不是T型)

  2. 标记的大小为void*。并且用户无需了解Tag的真实类型。

  3. 两个标签相同 - 它们指的是同一个对象。

  4. (摘要,从用户的角度来看)Handle<T>void** - &gt; void*

  5. 所以原来的bool operator==(Handle<S> that)正在做我们应该做的事情:比较标签的值。但请先查看指针。