PHP如何处理一个引用自身作为元素的数组?

hal*_*.am 17 php arrays recursion reference

让我们说我声明一个数组:

$data = array( 'foo' => 'bar' );
Run Code Online (Sandbox Code Playgroud)

现在我将添加对自身的引用作为新元素:

$data['baz'] = &$data;
Run Code Online (Sandbox Code Playgroud)

转储内容$data将导致:

Array
(
[foo] => bar
[baz] => Array
    (
        [foo] => bar
        [baz] => Array
         *RECURSION*
    )

)
Run Code Online (Sandbox Code Playgroud)

现在,我可以转储内容,$data['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']结果将与上面的内容完全相同,因为数组有一个指向自身的指针作为元素.

我想知道的是,如果php将数组作为一组数据处理,其指针与我在使用时调用的指针完全相同,$data或者它是否完全不同.

此外,PHP可以在返回内容时尝试内存不足$data{['baz']*n}吗?

Jon*_*Jon 10

在PHP内部,所有内容都存储在名为ZVAL变量容器中.由ZVAL表示,每个键和内部的每个值都是ZVAL等.$data$data

所以在初始赋值之后,从PHP创建了三个ZVAL:

   /-------------------\      /-------------------\   
   | ZVAL #1           |  /==>| ZVAL #2           |   
   |   type: array     |  |   |   type: string    |   
   |   data: [         |  |   |   data: "foo"     |
   |      {            |  |   \-------------------/
   |          key: =======/                         /-------------------\
   |          val: ================================>| ZVAL #3           |
   |      }            |                            |   type: string    |
   |   ]               |                            |   data:  "bar"    |
   \-------------------/                            \-------------------/
Run Code Online (Sandbox Code Playgroud)

注意:数组项的内部表示与上面显示的不对应; 我不想用不必要的细节来加重答案.出于同样的原因,还简化了ZVAL的表示.如果您想了解有关PHP内部的更多信息,请阅读源代码和/或此内容.

您可以看到,通过查看它们的ZVAL,无法确定"foo""bar"被用作数组键/值对的事实:您必须知道它们是由数组引用的.

在赋值之后$data['baz'] = &$data,你现在有了一个循环引用:在ZVAL#1中的某个地方有一个指向ZVAL#1的指针:

   /-------------------\      /-------------------\   
   | ZVAL #1           |  /==>| ZVAL #2           |   
/=>|   type: array     |  |   |   type: string    |   
|  |   data: [         |  |   |   data: "foo"     |
|  |      {            |  |   \-------------------/
|  |          key: =======/                         /-------------------\
|  |          val: ================================>| ZVAL #3           |
|  |      },           |                            |   type: string    |
|  |      {            |                            |   data: "bar"     |
|  |          key: =========================\       \-------------------/
|  |          val: =========\               |       
|  |      }            |    |               |       /-------------------\
|  |   ]               |    |               \======>| ZVAL #4           |
|  \-------------------/    |                       |   type: string    |
|                           |                       |   data: "baz"     |
\===========================/                       \-------------------/
Run Code Online (Sandbox Code Playgroud)

那么PHP如何解决$data['baz']['baz']?它知道它$data由ZVAL#1表示,它看到你试图用数组语法索引它.它查看ZVAL,看到它是一个数组,找到具有键的项"baz"并获取代表它的ZVAL.你知道什么?那是ZVAL#1再一次.总结了决议$data['baz'].

在下一步,它会发现您正在尝试索引$data['baz']为数组.它知道$data['baz']由ZVAL#1表示,所以同样的事情最终会再次发生,依此类推.

您将注意到上述过程不涉及存储任何中间结果(第一步和第二步完全独立),这意味着在尝试解析阵列访问时,PHP虚拟机没有资源限制.

  • **+ 1**可爱的答案 (2认同)
  • @BobKruithof:很高兴能帮忙,是的,我做了:-) (2认同)