PHP如何处理将自身作为元素引用的数组?
假设我声明一个数组:PHP如何处理将自身作为元素引用的数组?,php,arrays,recursion,reference,Php,Arrays,Recursion,Reference,假设我声明一个数组: $data = array( 'foo' => 'bar' ); 现在,我将添加对自身的引用作为新元素: $data['baz'] = &$data; 转储$data的内容将导致: Array ( [foo] => bar [baz] => Array ( [foo] => bar [baz] => Array *RECURSION* ) ) 现在,我可以转储$d
$data = array( 'foo' => 'bar' );
现在,我将添加对自身的引用作为新元素:
$data['baz'] = &$data;
转储$data
的内容将导致:
Array
(
[foo] => bar
[baz] => Array
(
[foo] => bar
[baz] => Array
*RECURSION*
)
)
现在,我可以转储$data['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']
的内容,结果将与上述内容完全相同,因为数组有一个指向自身的指针作为元素
我想知道的是,php是否将数组作为一组数据处理,其中的指针与我在使用$data
时调用的指针完全相同,或者它是否执行完全不同的操作
另外,PHP在返回
$data{['baz']*n}
的内容时是否会耗尽内存?在PHP内部,所有内容都存储在一个名为$data
由ZVAL表示,$data
中的每个键和每个值都是ZVAL,等等
因此,在初始赋值之后,from PHP创建了三个ZVAL:
/-------------------\ /-------------------\
| ZVAL #1 | /==>| ZVAL #2 |
| type: array | | | type: string |
| data: [ | | | data: "foo" |
| { | | \-------------------/
| key: =======/ /-------------------\
| val: ================================>| ZVAL #3 |
| } | | type: string |
| ] | | data: "bar" |
\-------------------/ \-------------------/
注意:数组项的内部表示与上面显示的内容不一致;我不想给答案添上不必要的细节。出于同样的原因,ZVAL的表示也被简化。如果您想了解更多关于PHP内部的信息,请阅读源代码和/或
您可以看到,“foo”
和“bar”
被用作数组键/值对的事实无法通过查看它们的zval来确定:您必须知道它们正被数组引用
在赋值$data['baz']=&$data
之后,您现在有了一个循环引用:ZVAL#1内的某个地方有一个指向ZVAL#1的指针:
那么PHP如何解析$data['baz']['baz']?它知道$data
由ZVAL#1表示,并且它看到您正试图使用数组语法索引到它。它查看ZVAL,发现它是一个数组,找到具有键“baz”
的项,并获取表示它的ZVAL。你知道什么?这又是ZVAL#1。这就结束了$data['baz']
的解析
在下一步中,它会看到您正试图将$data['baz']
作为一个数组进行索引。它知道,$data['baz']
由ZVAL#1表示,因此同样的事情最终会再次发生,以此类推
您会注意到,上面的过程不涉及存储任何中间结果(第一步和第二步完全独立),这意味着在尝试解析数组访问时,PHP虚拟机不会达到任何资源限制。实际上,要理解这一点,您需要了解什么是PHP数组。它们不是列表或类似的东西,它们是散列,简而言之。因此PHP存储了一个引用,它是键。问题是,在“递归”数组中,这样的引用指向它是另一个元素,仅此而已(即,它仍然是引用,仅此而已)。而且-不,如果在每次迭代时重新分配元素,就不会出现内存溢出的情况。这就像一个循环链表。它只对单个循环使用内存,而不是对所有副本使用无限内存。数组没有“列”,列是您在将数组元素可视化呈现为表时选择的解释数组元素的方式。@meagar是这样的。此外,虽然我对这一点有正确的想法,但我会等待有人以更正式和更严格的方式解释:)谢谢你的详细回答。这正是我想要的。还有一个问题:你自己键入ascii码了吗?;)@很高兴能帮上忙,是的,我帮了:-)
/-------------------\ /-------------------\
| 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" |
\===========================/ \-------------------/