foreach中的“&”符号带来的陷阱

之前也遇到过此类问题,这里整理一下,加深印象!

有这样一段代码:

问题是,输出结果是什么。

由于以引用方式遍历,$item依次指向数组中每个元素的值,对$item的修改都直接反映到了数组元素中,所以第一个foreach后,$items中的元素分别是a4, b4, c4。这一点还是比较容易理解的。

问题在于,第二个foreach后,输出的内容是什么呢?有人可能会说是a4b4c4,因为数组元素的值本是如此嘛!

但很遗憾,运行结果是a4b4b4!

何为引用?

在PHP中,变量名和变量内容是不一样的,所以同样的内容可以有不同的名字。

引用意味着可以使用不同的名字访问同一个变量内容。换句话说,引用是符号表别名。

如果指定了$a = &$b,那么$a和$b便指向了同一个变量内容。

如果要解除这种引用关系,可以用unset()。

为什么和预想不一样?

问题就在于,第二个foreach中的$item,这名字是上个foreach中以引用方式用过的。在foreach遍历结束后,$item指向了$items中最后一个元素的值,也就是c4。

所以在第二个foreach中,遍历数组中第一个值a4时,$item被赋值为a4,并输出了a4。同时,$item指向的数组元素值c4也被改为a4,也就是此时,$items[2]的值已被改为a4。

遍历第二个值b4时,类似地,$item被赋值为b4,并输出了b4,和$item指向同一数据存储位置的$items[2]也被改为了b4。

遍历第三个值,也就是$items[2]时,如上面所说,本身已变为b4,$item被赋值为b4,输出b4,本来的b4被再次更改为b4。

最后,$items中元素的值分别为a4,b4,b4。

如何解决此类异常?

可见,上面的情况不是我们希望看到的。经过分析,我们已经知道,捣鬼的就是第一个foreach中的变量别名$item,那么解除这种引用关系即可,也就是unset($item)。

实际上,php官方建议在以引用方式遍历数组后,立即用unset()解除引用。以避免造成异常。

参考资料

引用的解释:http://php.net/manual/zh/language.references.php

foreach:http://php.net/manual/zh/control-structures.foreach.php

张贴在PHP
使用 标记

发表评论

电子邮件地址不会被公开。 必填项已用*标注