PHP中foreach循环中运用引用要小心的地点

一、问题 先看贰个例子:

复制代码 代码如下:

<?php
$ar = array(1, 2, 3);
var_dump($ar);
foreach ($ar as &$v) {}
foreach ($ar as $v) {}
var_dump($ar);
?>
输出为:

foreach ($array as &$row) {
$row = explode(‘/’, $row);
}
foreach ($array as $row) {
//do something
}

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  &int(2)
}
???为何一贯不进展赋值操作,数组最终一个要素的值却发生了改观吗?

那样写,在第一个循环会出逻辑错误,参与第一个循环中do
something的地方是出口$row,循环到终极四个的时候的输出是倒数第2个要素,并不是终极贰个

自家早已开采了那些标题,一开首感到是 PHP 的 bug,就扔着没管它, foreach
中不应用引用就没事, 用 foreach $k => $v 然后 $ar[$k]
来改造原始数组, 略微损失点功效。

要如此写

二、分析

复制代码 代码如下:

今日花了点时间,看了 参考 中的文章,
算是有个别精晓有些了,原本是其同样子的:

foreach ($array as &$row) {
$row = explode(‘/’, $row);
}
unset($row);
foreach ($array as $row) {
//do something
}

在施行第贰个应用援引的 foreach 时, 一发端, $v 指向 $ar[0]
的蕴藏空间,空间内囤积着 1 , foreach 结束时, $v 指向 $ar[2]
的积累空间,空间内部存款和储蓄器储着 3 。 下边要起来实施首个 foreach
了,注意和率先个 foreach 区别, 第三个 foreach
未有运用引用,那么正是赋值格局, 将要 $ar 的值依次 赋值 给 $v 。
进行到第一个因素时,要将 $ar[0] 赋值给 $v 。
难点就在此地,由刘恒好施行完第七个 foreach, $v
不是两个新变量,而是已经存在的、指向 $ar[2] 的十二分 援用 ,
如此一来,对 $v 举行赋值的时候,就将 $ar[0] = 1 写入了 $ar[2]
的实际上存款和储蓄空间, 也正是对 $ar[2] 实行赋值。 由此及彼,第一个 foreach
实践的结果, 便是数组的末梢多个要素变为了尾数第二个因素的值。 参谋小说 第22中学有详尽的暗示图。

要么第三个循环这么写

倘若说那是一个错误,那么错误的由来就在于对援引变量的利用。
当援用变量指向和任何变量时,退换引用变量的值当然会耳闻则诵到她本着的其他变量。
单独说哪个人都知情,但在这一个 foreach 例子中,凑巧了,
同八个变量一回被使用,前一次是援引的身份,后一回是平凡变量身份,
就产生了预想之外的效果。 PHP
的开辟者也以为,这种情状属于语言特征产生的,不是 bug。
的确,假设要修复这些难点,一种格局是对 foreach 举行极度管理之外,
另外一种正是限量 foreach 中 $v 的效能域, 那三种艺术都与当前 PHP
的语言特征不符,开拓人员不愿改, 但依旧在 官方文书档案 中用 Warning
举办了证实。

复制代码 代码如下:

三、化解方法

foreach ($array as $key => $row) {
$array[$key] = explode(‘/’, $row);
}

一言以蔽之,但谈不上圆满,正是在选用了援用的 foreach 之后, unset 掉 $v ,
开始的例证改为:

说一下法规 第二个循环使用了援用,循环结束后,$row引用的是$array数组的末尾一个要素,当初始首个循环的时候,$row变量每一遍循环都会被赋一个新值,在php中,如若多个内部存款和储蓄器空间是被援引的,那么当更动它的时候是平素改动那块内部存款和储蓄器空间的值,也正是说,当第贰个foreach的首先次巡回,$array的最后三个因素的值就被改成为$array的率先个要素的值,第一回巡回的时候,改动为第二个因素的值,尾数第叁遍巡回的时候,被改造为尾数第三个成分值,而最后贰回巡回的时候得道的值必然是非常尾数第一个值
理所必然,如若php的for循环有作用域的话,也不会油可是生此难题…..

<?php
$ar = array(1, 2, 3);
var_dump($ar);
foreach ($ar as &$v) {}
unset($v);
foreach ($ar as $v) {}
var_dump($ar);
?>
运作结果:

你也许感兴趣的篇章:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

参考

Bug #29992 foreach by reference corrupts the
array:https://bugs.php.net/bug.php?id=29992
References and
foreach:http://schlueters.de/blog/archives/141-References-and-foreach.html

你或者感兴趣的稿子:

发表评论

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

网站地图xml地图