数组循环改变元素类型
Looping in array changes element type
考虑这个 PHP 代码片段,它在数组 中通过值引用 循环:
$arr = [1 ,2 , 3];
var_dump($arr);
echo '<br>';
foreach ($arr as &$val) { // note ampersand sign
// Anything
}
var_dump($arr);
现在首先 var_dump() 发出
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
但是第二个发出
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(3) }
因此,通过引用在数组中循环已将最后一个值类型从整数更改为整数 reference!
怎么可能呢?为什么 PHP 决定自己更改元素类型,而开发人员无意这样做?
要了解此行为,您需要了解一些有关 PHP 的事情:
- PHP 中的引用是 对称的:你没有 "create a reference to a variable",你 "add the variable to a reference set".
- 一个
foreach
by reference和一系列的by reference赋值是一样的,一个接一个。
- 数组值本身被视为变量,并且可以具有所有相同的类型信息,包括作为引用集的一部分。
所以让我们"unroll"你的循环:
// create a reference set containing $val and $arr[0]
$val =& $arr[0];
// remove $val from the first reference set,
// and create a second reference set containing $val and $arr[1]
$val =& $arr[1];
// remove $val from the second reference set,
// and create a third reference set containing $val and $arr[2]
$val =& $arr[2];
此时,$arr[0]
和$arr[1]
都在大小为1的参考集中,所以可以看作"normal values"。但是,$arr[2]
仍然在 $val
的参考集中。
这意味着对 $arr[2]
的任何更改都将反映在 $val
中,对 $val
的任何更改都将反映在 $arr[2]
中。这就是为什么 var_dump
用 &
注释该项目,以表明更改它也会更改其他地方的另一个变量。
这就是为什么在使用 foreach-by-reference 之后总是 运行 unset($val);
是一个好习惯。
考虑这个 PHP 代码片段,它在数组 中通过值引用 循环:
$arr = [1 ,2 , 3];
var_dump($arr);
echo '<br>';
foreach ($arr as &$val) { // note ampersand sign
// Anything
}
var_dump($arr);
现在首先 var_dump() 发出
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
但是第二个发出
array(3) { [0]=> int(1) [1]=> int(2) [2]=> &int(3) }
因此,通过引用在数组中循环已将最后一个值类型从整数更改为整数 reference! 怎么可能呢?为什么 PHP 决定自己更改元素类型,而开发人员无意这样做?
要了解此行为,您需要了解一些有关 PHP 的事情:
- PHP 中的引用是 对称的:你没有 "create a reference to a variable",你 "add the variable to a reference set".
- 一个
foreach
by reference和一系列的by reference赋值是一样的,一个接一个。 - 数组值本身被视为变量,并且可以具有所有相同的类型信息,包括作为引用集的一部分。
所以让我们"unroll"你的循环:
// create a reference set containing $val and $arr[0]
$val =& $arr[0];
// remove $val from the first reference set,
// and create a second reference set containing $val and $arr[1]
$val =& $arr[1];
// remove $val from the second reference set,
// and create a third reference set containing $val and $arr[2]
$val =& $arr[2];
此时,$arr[0]
和$arr[1]
都在大小为1的参考集中,所以可以看作"normal values"。但是,$arr[2]
仍然在 $val
的参考集中。
这意味着对 $arr[2]
的任何更改都将反映在 $val
中,对 $val
的任何更改都将反映在 $arr[2]
中。这就是为什么 var_dump
用 &
注释该项目,以表明更改它也会更改其他地方的另一个变量。
这就是为什么在使用 foreach-by-reference 之后总是 运行 unset($val);
是一个好习惯。