为啥 PHP 数组的元素被引用分配时会被修改?
Posted
技术标签:
【中文标题】为啥 PHP 数组的元素被引用分配时会被修改?【英文标题】:Why does a PHP array get modified when it's element is reference-assigned?为什么 PHP 数组的元素被引用分配时会被修改? 【发布时间】:2013-07-05 21:10:36 【问题描述】:当引用分配数组的元素时,数组的内容会被修改:
$arr = array(100, 200);
var_dump($arr);
/* shows:
array(2)
[0]=>
int(100) // ← ← ← int(100)
[1]=>
int(200)
*/
$r = &$arr[0];
var_dump($arr);
/* shows:
array(2)
[0]=>
&int(100) // ← ← ← &int(100)
[1]=>
int(200)
*/
Live run.(Zend 引擎可以正常工作,而 HHVM 显示“进程退出,代码为 153”。)
为什么要修改元素?
为什么我们看到的是&int(100)
而不是int(100)
?
这看起来很奇怪。这种奇怪的解释是什么?
【问题讨论】:
我无法使用提供的代码重现这一点。使用 php 5.4.6 我查过了,真的很奇怪。因为没有任务。我检查了writecodeonline.com/php @Robert 可以在这里重现,PHP_VERSION 在这里是 5.4.15 即使在 php 4 中也有相同的行为 3v4l.org/B2DgI 【参考方案1】:我之前回答过这个问题,但现在找不到答案。我相信它是这样的:
引用只是符号表中相同值的“附加”条目。符号表只能有它指向的 values,而不是 values 中的值。符号表不能指向数组中的索引,它只能指向一个值。因此,当您要引用数组索引时,将该索引处的值从数组中取出,为它创建一个符号,并且数组中的槽获得对该值的引用:
$foo = array('bar');
symbol | value
-------+----------------
foo | array(0 => bar)
$baz =& $foo[0];
symbol | value
-------+----------------
foo | array(0 => $1)
baz | $1
$1 | bar <-- pseudo entry for value that can be referenced
因为这是不可能的:
symbol | value
-------+----------------
foo | array(0 => bar)
baz | &foo[0] <-- not supported by symbol table
上面的$1
只是一个任意选择的“伪”名称,它与实际的 PHP 语法或内部实际引用该值的方式无关。
根据 cmets 的要求,这里符号表通常在引用中的行为方式:
$a = 1;
symbol | value
-------+----------------
a | 1
$b = 1;
symbol | value
-------+----------------
a | 1
b | 1
$c =& a;
symbol | value
-------+----------------
a, c | 1
b | 1
【讨论】:
@deceze,您在符号值表中使用的 字符 令人困惑...您将如何在$a = 1; $b = 1; $c =& $a;
这一行之后绘制符号值表? (只需将其作为参考以正确理解您的意思)
@deceze。 Ic,所以在$baz =& $foo[0];
之后,而不是baz | $1
$1 | 'bar'
,你实际上的意思是我们得到baz, $1 | 'bar'
对吧?
@Pacerier 这是另一种看待它的方式。我不知道说$baz
指的是值,$foo[0]
是伪链接,它也指的是相同的值是否更正确;或者$baz
和$foo[0]
是否都引用了引用该值的伪链接。但是,是的,你明白了。
@deceze,嗯,我不太明白你所说的 “伪链接” 是什么意思……不就是 $baz
和 $foo[0]
两个不同的符号指向同一个 zval 容器 [type='string', value='baz', refcount=2, is_ref=true]?
@Pacerier 差不多。 $foo[0]
不能是符号。 foo
是一个包含数组的符号。该数组的索引[0]
是对符号表中包含您提到的zval 的条目的引用,bar
也指的是该zval(无论是直接还是间接)。以上是关于为啥 PHP 数组的元素被引用分配时会被修改?的主要内容,如果未能解决你的问题,请参考以下文章