美工统筹SEO,为企业电子商务营销助力!
PHP的foreach中利用援用时须要注重的一个题目和处置体例
一佰互联网站建造(www.taishanly.com) 宣布日期 2020-04-29 09:01:10 阅读数: 181
一、题目
先看一个例子:
<?php
$ar = array(1, 2, 3);
var_dump($ar);
foreach ($ar as &$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(2)
}
???为甚么不停止赋值操纵,数组最初一个元素的值却发生了转变呢?
我早就发明了这个题目,一起头觉得是 PHP 的 bug,就扔着没管它, foreach 中不利用援用就没事, 用 foreach $k => $v 而后 $ar[$k] 来转变原始数组, 略微丧失点效力。
二、阐发
明天花了点时辰,看了 参考 中的文章, 算是略微大白一点了,本来是这个模样的:
在履行第一个利用援用的 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 履行的成果, 便是数组的最初一个元素变成了倒数第二个元素的值。 参考文章 2 中有具体的表示图。
若是说这是一个毛病,那末毛病的缘由就在于对援用变量的利用。 当援用变量指向和其余变量时,转变援用变量的值固然会影响到他指向的其余变量。 零丁说谁都大白,但在这个 foreach 例子中,恰巧了, 统一个变量两次被利用,前一次是援用的身份,后一次是通俗变量身份, 就发生了料想以外的成果。 PHP 的开辟者也以为,这类环境属于说话特征形成的,不是 bug。 简直,若是要修复这个题目,一种体例是对 foreach 停止特别处置以外, 别的一种便是限定 foreach 中 $v 的感化域, 这两种体例都与今朝 PHP 的说话特征不符,开辟职员不愿改, 但仍是在 官方文档 顶用 Warning 停止了申明。
三、处置体例
简略,但谈不上完善,便是在利用了援用的 foreach 以后, unset 掉 $v , 起头的例子改成:
<?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:http://bugs.php.net/bug.php?id=29992
References and foreach:http://schlueters.de/blog/archives/141-References-and-foreach.html