按引用分配 PHP 误解

Assign by reference PHP misunderstaning

下面给出的代码中$arr[0] result "2" 的含义是什么,$arr2 是复制$arr 并将其第一个值增加一个,所以$arr2[0] 的结果为 "2"正在理解,但是 $arr 发生了什么,当我通过引用 $arr[0] 传递给 $a 时 $a=&$arr[0] $arr[0] 的结果是 2,当我通过它时value $a=$arr[0[ $arr[0] 的结果应该设置为 1,谁能告诉我这个?

<?php
$a = 1;
$arr = array(1);
$a = &$arr[0];
$arr2 = $arr;
$arr2[0]++;
echo $arr[0]. "<br>";//2
echo $arr2[0]. "<br>";//2
?>

不确定这是否是错误,但var_dump() 可以帮助解释。

<?php
$a = 1;
$arr = array(1);

var_dump( $arr );
$a = &$arr[0];
var_dump( $arr );

$arr2 = $arr;
$arr2[0]++;

输出:

array(1) {
  [0]=>
  int(1)
}

array(1) {
  [0]=>
  &int(1)
}

注意第二个var_dump()中的&int(1)。这告诉我们 $arr 的位置 #0 已变成指向 PHP 内存中某个位置的引用指针,而不是保留专用值。

因此,当您执行 $arr2 = $arr; 时,$arr2 也会接收到该引用指针。

PHP 中的引用不像指针;当您通过引用分配或传递某些内容时,您创建了我们可能称之为 "reference set" 的内容,其中 both 变量是对相同 "zval" 的引用(内存中的结构保存变量的类型和值)。

一个重要的结果是引用是对称的。我倾向于将引用赋值写成 $foo =& $bar 而不是 $foo = &$bar 以强调这一点:运算符不只是引用 $bar 并将其放入 $foo,它影响两个操作数。

考虑到这一点,让我们看一下您的示例:

$arr = array(1);

这将创建两个 zval:一个用于数组 $arr 本身,另一个用于该数组 ($arr[0]).0 位置的值。

$a =& $arr[0];

这会将 $a$arr[0] 绑定到参考集中。无论我们使用这些名称中的哪一个,我们都将使用之前创建的相同 zval,并且当前保存 1.

$arr2 = $arr;

这会将 $arr 的内容复制到新数组 zval,$arr2 中。但它不会将该数组中的引用解析为值,它只是复制 它们是引用的事实

所以 $arr2[0] 现在也是包含 $arr[0]$a 的参考集的一部分。

$arr2[0]++;

这增加了我们引用集指向的 zval,从 12

echo $arr[0]. "<br>";//2
echo $arr2[0]. "<br>";//2

由于它们都是同一参考集的一部分,因此它们都指向同一个 zval,即整数 2。


不可避免的问题是,"bug or feature?" 一个更有用的示例是将包含引用的数组传递给函数:

function foo($array) {
   $array[0] = 42;
   $array[1] = 69;
}
$a = 1;
$b = 1;
$foo = [ &$a, &$b ];
foo($foo);
echo $a; // 42
echo $b; // 69

像赋值一样,传入函数不会破坏引用,因此操作它们的代码可以安全地重构为多个函数。