先看下面代码

$arr1 = [1, 2];

foreach($arr1 as $key => $value) {
  $value = $value + 1;
} var_dump($key, $value); //结果输出1,3

说明:在上面的foreach循环中,当循环结束后,临时变量 $key和$value变量都不会被自动释放掉。值会被保存下来。而且此时修改$val的值不会影响$arr。

理解foreach的原理,对上面的结果不难理解,foreach循环时,每次循环就会把`$arr1`元素的值复制给临时变量:$key, $value。如,第一次循环时,如下

$key = 0;
$value = $arr1[0];

第二次循环时,如下

$key = 1;
$value = $arr1[1];

再看forach中使用引用

引用:如果想在遍历数组的过程中修改数组的元素,可以在foreach中对$val使用引用。此时被引用的元素$val指向当前数组元素的内存地址,即共享一段内存地址。因此修改$val的值会同时改变$arr[$key]的值。

$arr1 = [1, 2];
foreach($arr1 as $key => $value) {
$value = $value + 1;
}
var_dump($key, $value); //结果输出1,3 var_dump($arr1);
$arr1 的值 为 ['0' => 2, '1' => 3]

说明:$key , $value 的值和上面的非引用情况下一样。在foreach中使用&引用后,当foreach结束后,$key和$val变量也都不会被自动释放掉,但是此时$val和$arrcount($arr) - 1指向相同的内存地址。因此,此时修改$val的值也会改变了$arr[3]的值。

foreach 引用时,原理和上面一样,只不过是引用复制,原来如下

第一次循环:
$key = 0;
$value = &$arr1[0]; 第二次循环:
$key = 1;
$value = &$arr1[1];

再看个例子:

$arr1 = [1, 2];
foreach($arr1 as $key => &$value) {
$value = $value + 1;
}
var_dump($arr1); $value = 100; var_dump($arr1);

第二次输出 $arr1时,第二个元素的值也是100了。

理解了原理,就知道坑了。如果我们2个foreach循环,使用相同的临时变量就会有问题了,一个foreach在使用引用的时候。

如:

$arr1 = [1, 2];
foreach($arr1 as $key => &$value) {
$value = $value + 1;
}
//此时 $value = &$arr1[1] ,后面改变$value的值就会改变$arr1[1]元素的值。
$arr2 = [10, 20, 30];
foreach ($arr2 as $value) {
var_dump($arr1);
}

我们发现在循环$arr2时,$arr2元素复制给$value后,同时$arr1的最后一个元素的值也发生变化,此时等于$arr2此时指针对应元素的值。依次推,$arr1最后一个元素的值 = $arr2元素的最后一个值。

解决方法,使用unset()释放元素, 或者循环第2个数组的时候,使用不同的临时变量

$arr1 = [1, 2];
foreach($arr1 as $key => &$value) {
$value = $value + 1;
}
unset($value);
$arr2 = [10, 20, 30];
foreach ($arr2 as $value) {
var_dump($arr1);
}

foreach引用坑的更多相关文章

  1. 说说PHP中foreach引用的一个坑

    From: http://blog.csdn.net/yipiankongbai/article/details/45307767 先来看看下面这段代码: <?php $arr = array( ...

  2. php foreach引用赋值

    在写代码时发现php foreach引用赋值会导致意外的行为. 代码示例: <?php $arr = array('a','b','c'); foreach($arr as $k=>&am ...

  3. foreach 引用传值&

    foreach  引用传值& php 怎么在foreach中循环数组   ,的时候添加元素跟值 foreach($arr as $key => &$vo){ //注意,由于上面遍 ...

  4. PHP 数组 foreach引用导致的bug

    <?php $arr = array('a', 'b', 'c'); foreach($arr as &$v) {} foreach($arr as $v) {} var_dump($a ...

  5. for-each的坑(Hollis)

    直接用代码来说明: public class ForEach { public static void main(String[] args) { List<String> list = ...

  6. Visual Studio 2015下编译zmq项目下其他项目踩进的项目引用坑

    PS.在之前的一篇文章中介绍了如何用Visual Studio 2015编译zmq,在编译同解决方案中除了libzmq之外的项目例如inproc_thr时会报错误,具如下: Severity Code ...

  7. PHP foreach引用&

    将以下代码打印 $variable = ['a', 'b', 'c']; foreach ($variable as $key => &$value) { } foreach ($var ...

  8. PHP foreach 引用 &

    以前用foreach,总喜欢在第二次遍历时改变value的拼写,比如 $x = array("a", "b", "c"); foreach ...

  9. forEach的坑

    使用js里的forEach来遍历数组的时候需要注意的是:break,return语句不能使其中断,它还是会继续遍历完数组的每一个元素 错误代码: function nameExit(name){ da ...

随机推荐

  1. 内核用户模式调试支持(Dbgk)

    简介 将详细分析Windows调试的内核模式接口.希望读者对C和通用NT内核体系结构和语义有一些基本的了解.此外,这并不是介绍什么是调试或如何编写调试器.它可以作为经验丰富的调试器编写人员或好奇的安全 ...

  2. gj的交换机在升级了ios之后最新数据不刷新,

    下午2点开始升级5点结束,之后监控项获取不到最新数据,显示网络接口一直是down的状态,但是登上设备之后显示的是正常up状态, 怀疑是自动发现规则的问题,但是查看之后都是1个小时,应该不会, 这时候诡 ...

  3. isntall

    #! /bin/bash # zabbix server address zabbix='10.10.238.110' # repo address REPO='10.10.238.114:4507' ...

  4. chmod/chown/chgrp/chattr

    权限组合其实就是二进制的组合 注意,用户只能修改属于自己的文件 仅管理员可以修改文件的数组和属主 chmod 三种使用方法 文件的特殊权限 SUID SGID Sticky chowm 修改文件,目录 ...

  5. CSPS_110

    永远不要相信出题人诸如“保证图联通”之类的鬼话. T1 最优情况一定为从LR最高的不同位以下全是1 T2 折半搜索 T3 1.我算法不是mlog^2m,最坏情况下mlogm再乘个根号m, 考试的时候没 ...

  6. [bzoj1001]狼抓兔子 最小割

    题意概述:给出一张无向图,每条边有一个权值,割掉这条边代价为它的权值,求使起点不能到达终点的最小代价. 显然能看出这是个最小割嘛,然后最小割=最大流,建图的时候特殊处理一下再跑个最大流就好了. #in ...

  7. python实现:判断某一天是那一年中的第几天

    方法1:先判断是否是闰年,然后再利用求和,得出某一天是第几天 # 方法1:low版 def func1(year, month, day): # 分别创建平年,闰年的月份天数列表(注意列表下标从0开始 ...

  8. ubuntu之路——day15.1 只用python的numpy在底层检验参数初始化对模型的影响

    首先感谢这位博主整理的Andrew Ng的deeplearning.ai的相关作业:https://blog.csdn.net/u013733326/article/details/79827273 ...

  9. DELPHI无类型参数

    DELPHI无类型参数 有不少Delphi新手对过程(函数)的无类型参数感到困惑,不知该传递什么类型.其实,Delph中有不少这类无类型参数,如常用的Move过程,只要把它当着一个Byte类型的数组看 ...

  10. spark streaming 流式计算---跨batch连接池共享(JVM共享连接池)

    在流式计算过程中,难免会连接第三方存储平台(redis,mysql...).在操作过程中,大部分情况是在foreachPartition/mapPartition算子中做连接操作.每一个分区只需要连接 ...