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虚拟机没有资源限制.