我只是在写一个简单的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?
?>
这将输出以下内容:
Array
(
[0] => foo
[1] => bar
[2] => baz
)
Array
(
[0] => foo
[1] => bar
[2] => bar
)
这是一个bug还是应该发生的一些非常奇怪的行为?
发布于 2011-11-22 08:27:22
在第一个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 )
在循环结束时,$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 )
您将注意到,每次数组将一个新值放入$item
时,它也会用相同的值更新$arr[3]
,因为它们仍然指向相同的位置。当循环到达数组的第三个值时,它将包含值bar
,因为它是由该循环的前一次迭代设置的。
这是个bug吗?
不是的。这是引用项的行为,而不是bug。它将类似于运行以下内容:
for ($i = 0; $i < count($arr); $i++) { $item = $arr[$i]; }
foreach循环在本质上并不特殊,因为它可以忽略引用的项。它只是在每次都将变量设置为新值,就像在循环之外一样。
发布于 2011-11-22 08:33:19
正如animuson指出的那样,$item
是对$arr[2]
的引用,并且正在被第二个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?
发布于 2011-11-26 01:40:14
虽然这可能不是正式的bug,但在我看来确实是。我认为这里的问题是,当循环退出时,我们期望$item
超出范围,就像在许多其他编程语言中一样。然而,情况似乎并非如此。
这个代码..。
$arr = array('one', 'two', 'three');
foreach($arr as $item){
echo "$item\n";
}
echo $item;
给出输出...
one
two
three
three
正如其他人已经说过的,您使用第二个循环覆盖了$arr[2]
中的引用变量,但这只是因为$item
从未超出作用域。你们觉得呢..。虫子?
https://stackoverflow.com/questions/8220399
复制相似问题