PHP中使用foreach和引用导致程序BUG的问题介绍

yipeiwu_com5年前PHP代码库
复制代码 代码如下:

$a = array(1, 2);
$b = array(11, 12);
foreach($a as &$r){
}
foreach($b as $r){
}
echo $a[1]; // 输出 12

两个的循环的本意可能是: 第一个循环需要在循环中修改元素的内容, 所以使用引用; 但第二个循环只是把 $r 当作一个临时变量. 可是, 为什么 $a[1] 的值发生了改变呢?

当对 $a 的迭代完成后, $r 是 $a[1] 的引用, 改变 $r 的值, 就是改变 $a[1]. 这时, 你可以会奇怪, 代码中并没有修改 $r, 也没有修改 $a[1] 呀?

其实, foreach 是操作的是数组的拷贝, 所以, 后一个迭代相当于:
复制代码 代码如下:

for($i=0; $i<count($b); $i++){
$r = $b[$i]; // 修改了 $r! 相当于 $a[1] = $b[$i];
}

为了避免这种情况, 应该在第一个迭代之后, 执行
复制代码 代码如下:

unset($r);

从当前环境中删除 $r 这个变量(引用变量).

即使不是前面的例子, 在第一个迭代之后, 仍然十分可能再执行类似的语句:
复制代码 代码如下:

$r = 123;

循环变量一般是临时变量, 同一个变量名在代码不同的地方表示不同的东西, 但变量的作用域又存在于循环之外. 这就是这种作用域规则的坏处, 加上”变量不声明即使用”的坏外, 再加上变量无类型的坏处.

所以, 在 PHP 中使用引用变量, 应该在引用使用完之后, 应该 unset(). 所有变量在使用之前应该先 unset().

相关文章

php中的抽象方法和抽象类

1、什么是抽象方法? 我们在类里面定义的没有方法提的方法就是抽象方法。所谓的没有方法体指的是,在声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象...

PHP遍历文件夹与文件类及处理类用法实例

本文实例讲述了PHP遍历文件夹与文件类及处理类用法,非常具有实用价值。分享给大家供大家参考。具体方法如下: FindFile.class.php类文件用于遍历目录文件,具体代码如下:...

用PHP实现读取和编写XML DOM代码

复制代码 代码如下: // 用 DOM 读取 XML $doc = new DOMDocument(); $doc->load(‘test.xml'); $books = $doc...

PHP封装的数据库保存session功能类

本文实例讲述了PHP封装的数据库保存session功能类。分享给大家供大家参考,具体如下: PHP用数据库保存session类: <?php class SafeSes...

PHP实现求两个字符串最长公共子串的方法示例

本文实例讲述了PHP实现求两个字符串最长公共子串的方法。分享给大家供大家参考,具体如下: 前面一篇PHP实现求解最长公共子串问题的方法是基于java改进而来,这里再来看另一种公共子串算法...