PHP 在 foreach 中使用 "引用" 的注意事项
PHP中使用引用是不好的,您应当尽量避免使用它们。现在有一个用例,会导致意外的行为:
该代码的输出是什么?
1 |
|
我们遍历数组两次而不做任何事情,因此结果应该没有改变。对吗?错!实际结果如下所示:
1 | Array |
为了理解为什么会发生这种情况,让我们回顾一下,看看PHP变量的实现方式以及引用的内容:
PHP变量由 标签(lable)
和 容器(container)
组成。标签是哈希表中的条目(引擎中有一些优化,因此它并不总是在哈希表中),它可以表示函数的符号表,数组或对象的属性表。因此,我们有一个名称和一个指向容器的指针。容器内部称为 zval
,用于存储值和一些元信息,该容器也可以是带有一组指向其他容器的标签的新哈希表,如果我们现在创建引用,则会导致第二个标签指向与另一个标签相同的容器。从那时起,这两个标签具有与容器相同的功能。
现在让我们分析上面的情况,它在图片中看起来像这样:
因此,我们有六个容器(全局符号表在顶部,一个容器包含一个名为 $a
的数组,左侧是一个容器,右侧是每个元素的一个容器)。
现在,我们开始第一次迭代:全局符号 $v
获取了一个新条目,并且 $v
成为对第一个数组元素的容器的引用:
因此,对 $a[0]
或 $v
的更改将进入同一容器,对另一个容器会产生影响。
当迭代继续进行时,引用将断开,并且 $v
将成为对不同元素的引用。在迭代结束之后,$v
是对最后一个元素的引用:
请记住:$v
是一个引用,意味着对 $v
的任何更改都会影响其他引用,在这种情况下,为 $a[3]
,到目前为止,没有什么特别的事情发生。
但是现在第二次迭代开始了,这一步将当前元素的值分配给 $v
,现在 $v
是对与 $a[3]
相同的元素的引用,因此通过为 $v
赋值,$a[3]
也将更改:
继续后续步骤:
现在我们可以很容易地猜测到最后一步会发生什么:$v
被分配了最后一个元素的值 $a[3]
,并且由于 $a[3]
是对 $v
的引用,因此它将自己分配给自己,什么也没发生:
这就是我们在上面看到的结果。
因此:请注意引用!它们会产生非常奇怪的效果。
想避免此类问题,可以使用不同的变量名,但这不是一个好办法,这为你的代码埋下了隐患;
或者使用 unset()
释放变量。
但我认为您应当尽量避免使用它们。