reg*_*ity 156 php arrays loops reference
我刚刚写了一个简单的PHP脚本,我有一些非常奇怪的行为.我把它减少到重新创建bug所需的最小值:
<?php
$arr = array("foo",
"bar",
"baz");
foreach ($arr as &$item) { /* do nothing by reference */ }
print_r($arr);
foreach ($arr as $item) { /* do nothing by value */ }
print_r($arr); // $arr has changed....why?
?>
Run Code Online (Sandbox Code Playgroud)
这输出:
Array
(
[0] => foo
[1] => bar
[2] => baz
)
Array
(
[0] => foo
[1] => bar
[2] => bar
)
Run Code Online (Sandbox Code Playgroud)
这是一个错误还是一些应该发生的奇怪行为?
ani*_*son 168
在第一个foreach循环之后,$item
仍然是对某个值的引用,该值也被使用$arr[2]
.因此,第二个循环中的每个foreach调用(不通过引用调用)将替换该值,从而替换$arr[2]
为新值.
所以循环1,值和$arr[2]
变为$arr[0]
,'foo'.
循环2,值和$arr[2]
变为$arr[1]
,即'bar'.
循环3,值和$arr[2]
变为$arr[2]
,'bar'(因为循环2).
值'baz'实际上在第二个foreach循环的第一次调用时丢失.
对于循环的每次迭代,我们将回显值$item
以及递归打印数组$arr
.
当第一个循环运行时,我们看到这个输出:
foo
Array ( [0] => foo [1] => bar [2] => baz )
bar
Array ( [0] => foo [1] => bar [2] => baz )
baz
Array ( [0] => foo [1] => bar [2] => baz )
Run Code Online (Sandbox Code Playgroud)
在循环结束时,$item
仍然指向同一个地方$arr[2]
.
当第二个循环运行时,我们看到这个输出:
foo
Array ( [0] => foo [1] => bar [2] => foo )
bar
Array ( [0] => foo [1] => bar [2] => bar )
bar
Array ( [0] => foo [1] => bar [2] => bar )
Run Code Online (Sandbox Code Playgroud)
您将注意到每个时间数组如何设置新值$item
,它也会$arr[3]
使用相同的值进行更新,因为它们仍指向同一位置.当循环到达数组的第三个值时,它将包含该值,bar
因为它只是由该循环的上一次迭代设置的.
不.这是引用项目的行为,而不是错误.它类似于运行类似:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
Run Code Online (Sandbox Code Playgroud)
foreach循环本质上并不特殊,它可以忽略引用的项目.它只是像每次循环一样将该变量设置为新值.
小智 28
$item
是$arr[2]
animuson指出的第二个foreach循环的引用和被覆盖.
foreach ($arr as &$item) { /* do nothing by reference */ }
print_r($arr);
unset($item); // This will fix the issue.
foreach ($arr as $item) { /* do nothing by value */ }
print_r($arr); // $arr has changed....why?
Run Code Online (Sandbox Code Playgroud)