为什么当 PHP 数组的元素被引用分配时会被修改?

Why does a PHP array get modified when it's element is reference-assigned?

提问人:Pacerier 提问时间:7/8/2013 最后编辑:Pacerier 更新时间:3/30/2015 访问量:246

问:

当 ref 分配数组的元素时,数组的内容将被修改:

$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 Engine 可以正常工作,而 HHVM 显示“进程退出,代码为 153”。

为什么要修改元素?

为什么我们看到而不是?&int(100)int(100)

这似乎很奇怪。这种奇怪的解释是什么?

PHP 数组 引用 php-internals

评论

0赞 Orangepill 7/8/2013
我无法使用提供的代码重现此内容。使用 PHP 5.4.6
0赞 Robert 7/8/2013
我检查过了,真的很奇怪。因为没有同化。我已经检查过 writecodeonline.com/php
0赞 Orangepill 7/8/2013
@Robert可以在这里重现,PHP_VERSION是 5.4.15 这里
0赞 Robert 7/8/2013
即使在 php 4 中也存在相同的行为
1赞 Amal Murali 7/8/2013
3v4l.org/B2DgI

答:

7赞 deceze 7/8/2013 #1

我不久前已经回答了这个问题,但现在找不到答案。我相信它是这样的:

引用只是符号表中相同值的“附加”条目。符号表只能包含它指向的值,而不能包含值中的。符号表不能指向数组中的索引,它只能指向一个值。因此,当您要引用数组索引时,将从数组中取出该索引处的值,为其创建一个符号,并且数组中的插槽获取对该值的引用:

$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

以上只是一个任意选择的“伪”名称,它与实际的PHP语法或内部实际引用值的方式无关。$1

根据注释中的要求,以下是符号表通常与引用的行为方式:

$a = 1;

symbol | value
-------+----------------
a      | 1


$b = 1;

symbol | value
-------+----------------
a      | 1
b      | 1


$c =& a;

symbol | value
-------+----------------
a, c   | 1
b      | 1

评论

0赞 Pacerier 8/8/2013
@deceze,您在符号值表中使用的字符令人困惑......您将如何在这条线之后绘制符号值表?(只需要它作为参考,以正确理解您在这里的意思)$a = 1; $b = 1; $c =& $a;
0赞 Pacerier 8/8/2013
@deceze。Ic,所以在行之后,而不是,你实际上意味着我们做对了?$baz =& $foo[0];baz | $1$1 | 'bar'baz, $1 | 'bar'
0赞 deceze 8/8/2013
@Pacerier 这是另一种看待它的方式。我不知道说它指的是值,是一个伪链接,也指同一个值,这是否更正确;或者是否两者都引用引用值的伪链接。但是,是的,你明白了。$baz$foo[0]$baz$foo[0]
0赞 Pacerier 8/8/2013
@deceze,嗯,我不太明白你所说的“伪链接”是什么意思。难道不是两个不同的符号指向同一个 zval 容器 [type='string', value='baz', refcount=2, is_ref=true]吗?$baz$foo[0]
0赞 deceze 8/8/2013
@Pacerier 差不多。 不能是符号。 是保存数组的符号。该数组的索引是对符号表中包含您提到的 zval 的条目的引用,也引用了该 zval(无论是直接还是间接)。$foo[0]foo[0]bar