按引用分配 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,从 1
到 2
。
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
像赋值一样,传入函数不会破坏引用,因此操作它们的代码可以安全地重构为多个函数。
下面给出的代码中$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,从 1
到 2
。
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
像赋值一样,传入函数不会破坏引用,因此操作它们的代码可以安全地重构为多个函数。