将指针指向指针......指针?

lo *_*cre 2 c++ pointers casting

我找到了这个片段

void* operator new(size_t nbytes)
{
  if (nbytes == 0)
    nbytes = 1;                    // so all alloc's get a distinct address
  void* ans = malloc(nbytes + 4);  // overallocate by 4 bytes
  *(Pool**)ans = NULL;             // use NULL in the global new
  return (char*)ans + 4;           // don't let users see the Pool*
}
Run Code Online (Sandbox Code Playgroud)

这里https://isocpp.org/wiki/faq/dtors

我花了一个多小时才试着理解它是*(Pool**)ans = NULL;做什么的. ans是一个void指针,所以我认为它被强制转换为Pool指针并且池设置为0.不是指针而是池本身,因为*左边的第三个.但Pool没有operator=定义.

pointer**在声明中显然是一个指向指针的指针......但在这种情况下,这对我来说没有任何意义,就像ans一个指针一样.

Jas*_*n C 6

Pool**这里使用的唯一原因是语义正确性,因为大概是"隐藏的"4字节头应该是指向a的指针Pool(因此ans是指向a的指针Pool,并且*(Pool **)ans具有类型Pool *).

你不能这样做*(Pool *)ans = NULL,除非你能够分配PoolNULL,这可能不是这里反正预期的效果.类似的东西*(int **)ans = NULL或更荒谬的东西*(Pool ******)ans = NULL会产生相同的最终效果,但如果最终意图是指向a的指针,那么它在语义上会很奇怪Pool.

在一天结束时,您将最终得到:

 +---+---+---+---+- - -
 | 0 | 0 | 0 | 0 | ... and nbytes more bytes
 +---+---+---+---+- - -

 ^ ans           ^ returned address (ans + 4)
Run Code Online (Sandbox Code Playgroud)

前4个字节是指向Pool某个地方的指针.

nbytes考虑这一点的另一种方法是忽略整个事情,考虑这种一般模式:

void * ptr = malloc(sizeof(TYPE));
*(TYPE *)ptr = VALUE;
Run Code Online (Sandbox Code Playgroud)

这应该是有道理的.现在,如果TYPE是a Pool *并且VALUE是NULL并且你适合该模式,你可以看到它仍然有意义:

void * ptr = malloc(sizeof(Pool *));
*(Pool **)ptr = NULL;
Run Code Online (Sandbox Code Playgroud)

然后在你的情况下你仍然基本上这样做,虽然你在最后分配一些额外的字节,但这与这里的类型无关.

顺便说一句,它可能会在这里(以及在语义上懒惰)要求4在任何地方进行硬编码而不是麻烦sizeof(Pool *).