通过引用分配PHP的误解

时间:2018-06-20 15:09:00

标签: php pass-by-reference

$ arr [0]结果“ 2”的含义在下面的代码中是什么,$ arr2正在复制$ arr并将其第一个值增加一个,因此$ arr2 [0]“ 2”的结果很明显,但是$ arr发生了什么,当我像这样将引用$ arr [0]传递给$ a时,这样$ a =&$ arr [0]的结果是$ arr [0]为2,当我将其传递给值$ 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
?>

2 个答案:

答案 0 :(得分: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)
}

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

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

答案 1 :(得分:2)

PHP中的引用不像指针。当您通过引用分配或传递某些内容时,您会创建我们可以称为“引用集”的内容,其中两个 变量都是对相同“ zval”的引用(内存中保存了类型和值的结构)变量)。

一个重要的后果是引用是对称的。我倾向于将引用分配写为$foo =& $bar而不是$foo = &$bar来强调这一点:运算符不仅会引用$bar并将其放入$foo,会同时影响两个操作符。

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

$arr = array(1);

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

$a =& $arr[0];

这会将$a$arr[0]绑定到参考集中。无论使用哪种名称,我们都将使用以前创建的相同zval,当前使用1

$arr2 = $arr;

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

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

$arr2[0]++;

这会将参考集所指向的zval从1增大到2

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

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


不可避免的问题是“错误还是功能?”一个更有用的示例是将包含引用的数组传递给函数:

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

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