PHP错误或我对语言的误解


PHP Bug or my misunderstanding of the language?

这是我不理解的代码(作为输出)。

<?php
$x = ['test1', 'test2', 'test3', 'test4'];
echo "First FOREACH'n";
foreach ($x as &$y)
{
    echo $y."'n";
}
echo "'n'nSecond FOREACH'n";
foreach ($x as $y)
{
    echo $y."'n";
}
?>

输出:

First FOREACH
test1
test2
test3
test4
Second FOREACH
test1
test2
test3
test3

PS:我在下运行

php -v
PHP 5.6.11-1ubuntu3.1 (cli) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

在第一个foreach语句之后,$y指向最后一个数组项:

$x = ['test1', 'test2', 'test3', 'test4'];
$y =& $x[3];

每当您为$y赋值时,原始数组都会被修改。

当第二个foreach开始时,在每次迭代中,来自$x的下一个值被放入$y。因此,在每次迭代中,原始数组将看起来像:

// first iteration
$x = ['test1', 'test2', 'test3', 'test1'];
// second iteration
$x = ['test1', 'test2', 'test3', 'test2'];
// third iteration
$x = ['test1', 'test2', 'test3', 'test3'];
// fourth iteration
$x = ['test1', 'test2', 'test3', 'test3'];

它更多的是一个功能,它记录在foreach手册页中

警告$value和最后一个数组元素的引用即使在foreach循环之后仍然保留。建议使用unset()销毁它。

手册页上有一些相关的评论,下面是其中一条http://php.net/manual/en/control-structures.foreach.php#111688

有关此情况的详细信息,请点击此处http://schlueters.de/blog/archives/141-References-and-foreach.html

我想你会得到这样的东西。

第一FOREACH测试1测试2第二FOREACH测试1测试1

因为您正在使用&将$y放在第一个foreach中,使$y引用$x,即整个数组$x。$y将一直是一个引用,直到您取消设置它为止。
所以…
因为您在下一个foreach中重用$y,PHP将$x两次设置为$y的第一个元素"test1"$x将是[测试1',测试1']。

使用引用时一定要小心,当您不再需要它们时一定要取消设置。

由于您的第一个循环,$y仍然是对最后一个数组项的引用,因此每次都会覆盖它。

当您在循环中使用引用时,建议使用unset()函数销毁它。

例如,当您创建一个Global变量时,这意味着您正在创建一个引用。

还有一个例子,当我们在一个对象中使用$this关键字时,我们正在创建该对象的引用,而不是再次复制。

好吧,我认为它是这样发生的:

当你的第一个循环完成时。数组中的最后一个元素仍然使用变量$y 进行引用

当第一个循环完成时,把你的数组想象成这样:

['test1', 'test2', 'test3', &'test4']

注意,我在最后一个元素处插入了&,因为它引用了变量$y

现在,当第二个循环开始时。$x中的每个元素都将被引用为$y,请记住,在您的数组$x中,最后一个元素仍由循环中的变量$y引用。

因此,数组$x中的最后一个元素在第二个循环的每次迭代中都会被修改。作为$y

['test1', 'test2', 'test3', &'test1'] <-- $y as being first element, notice that the last element is also $y ['test1', 'test2', 'test3', &'test2'] $y being 'test2' ['test1', 'test2', 'test3', &'test3'] $y as 'test3' ['test1', 'test2', 'test3', &'test3'] $y being the last element which is 'test3'