写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下:

<?php
$arr = ['a', 'b', 'c', 'd', 'e'];
foreach ($arr as $i=>&$a) {
$a = $a.'_'. $a;
echo $a .'<br>';
}
echo '<hr>';
foreach ($arr as $i=>$a) {
echo $a .'<br>';
}
echo '<hr>';
print_r($arr);

输出结果:

一开始看到第二个 foreach 输出的结果感觉很是莫名其妙,怎么会输出两个 d_d 呢?

仔细想了想,原来因为PHP foreach 中的 $a 的作用域是整个函数的局部变量,在循环外部仍然有效,而不是被封闭在循环内的,

所以当执行第二个foreach 时的 $a 并不是新的变量,而是仍然指向 $arr 数组第5个元素的地址引用,

当第二个 foreach 在循环时实际上是在不停的给 $arr 数组的第5个元素赋值,

具体赋值情况,

第一次:a_a 赋值给第5个元素, 结果为: [a_a, b_b, c_c, d_d,a_a]

第二次:b_b 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,b_b]

第三次:c_c 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,c_c]

第四次:d_d 赋值给第5个元素,结果为: [a_a, b_b, c_c, d_d,d_d]

第五次:此时因为第五个元素已经变成 d_d 又重新把 d_d 赋值给第5个元素,结果还是为: [a_a, b_b, c_c, d_d,d_d]

解决办法:

  1. 尽量不使用相同的循环变量名;
  2. 每次使用完或再次使用前进行 unset($a); 处理,解除地址应用

还是用上面代码示例:

$arr = ['a', 'b', 'c', 'd', 'e'];
foreach ($arr as $i=>&$a) {
$a = $a.'_'. $a;
echo $a .'<br>';
}
echo '<hr>';
echo $a;
echo '<hr>'; // 这里 unset 掉
unset($a); echo $a = 'ccc';
echo '<hr>';
print_r($arr);
echo '<hr>';
foreach ($arr as $i=>$a) {
echo $a .'<br>';
}
echo '<hr>';
print_r($arr);

输出结果:

现在就正常了,这些小细节一定要注意了

PHP关于foreach使用引用变量的坑的更多相关文章

  1. PHP中关于foreach使用引用变量的坑

    PHP版本为 5.6.12 代码如下:   1 2 3 4 5 6 7 8 9 10 11 12 <?php $arr = ['a', 'b', 'c', 'd', 'e']; foreach ...

  2. 【PHP】 foreach循环中变量引用的一道面试题

    $a = array('a','b','c'); foreach($a as &$v){} foreach($a as $v){ } var_dump($a); 现在.不要打开浏览器,猜测一下 ...

  3. PHP使用引用变量foreach时,切记其他循环不要使用同一个名字的变量

    foreach ($log['data'] as $k => &$value) { if ($value['token'] != 0) { $value['change_num'] = ...

  4. 引用变量 php面试总结1

    (1)PHP引用变量 概念:不同的变量名,访问同一个变量内容,使用& 知识点: 使用php函数 (a)memory_get_usage() 查看内存使用情况 eg // 定义一个变量 $a = ...

  5. php中foreach使用引用的陷阱

    有时候我们为了在循环过程中改变数组项的值,在foreach的时候变量入口可以加个&符合, 表示,循环过程中使用数组中原来的值,而不是一个复制的值,如 foreach ($array as &a ...

  6. PHP面试 PHP基础知识 一(引用变量)

    PHP引用变量 常见引用变量面试题: 什么是引用变量? 在PHP中用什么符号定义引用变量? 考点:PHP的引用变量的概念及定义方式 概念:在PHP中引用意味着用不用的名字访问同一个变量内容     定 ...

  7. Java基础-被final修饰的引用变量的指向

    final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象,那么该引用变量指向的对象的内容可变吗?看下面这个例子: public class Test { public static void ...

  8. PHP GC垃圾回收机制之引用变量回收周期疑问

    普通的引用变量的销毁大家都知道, 当unset的时候如果refcount = 0 则认为无用, 销毁. 但是手册中提到一点会有递归引用的问题,很是奇葩 代码如下 <?php $a = 1; $a ...

  9. C++引用变量(转)

    引用变量 c++中引用变量的使用: 定义: int rate=80; int  & pt=rate 1.pt 是引用变量,申明引用变量时必须将其初始化.pt 和rate 的值指向相同的内存变量 ...

随机推荐

  1. Scala开发环境搭建与资源推荐

    Scala开发环境搭建与资源推荐 本文介绍了Scala的开发环境,包括SDK.IDE的设置.常用资源列表等.Scala是一门静态语言,很有可能就是Java的继承者. AD: 2014WOT全球软件技术 ...

  2. 老调重弹--面向对象设计原则--GRASP设计原则

    GRASP概述 GRASP,全称General Responsibility Assignment Software Patterns,译为”通用职责分配软件原则“,包含以下原则和模式 控制器(Con ...

  3. Idea构建Maven项目教程

    Idea构建Maven项目,以及其中遇到的坑,及解决方案 步骤一:配置Idea的maven插件 步骤二:创建maven项目 file-->new-->project 下一步,设置group ...

  4. IP数据报是如何在网络中转发的?

    首先发送方抽取目的站的网络前缀,来判断是否目的站是否位于同一网络上,如果在二者有相同的网络前缀,则,直接使用直接交付的方式, 否则,使用由路由器互连的间接交付,这要借助IP路由表,采用表驱动法,路由表 ...

  5. IOS开发小功能1:引导页的开发

    效果图如上,实现的是一个页面引导页,最后跳到主页面,主页面是一个navigationController,但是导航栏给我隐藏了. 文件目录:自己定制的viewcontroller以及navigatio ...

  6. let和const关键词

    ECMAScript 6中的let和const关键词 2013-11-28 21:46 by BarretLee, 21 阅读, 0 评论, 收藏, 编辑 ECMAScript 6中多了两个定义变量的 ...

  7. 《C++游戏开发》笔记十三 平滑过渡的战争迷雾(一) 原理:Warcraft3地形拼接算法

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9611887 作者:七十一雾央 新浪微博:http:/ ...

  8. java的抽象类和抽象方法(注意查看如何调用抽象类中的非抽象方法)

    抽象类就是不能使用new方法进行实例化的类,即没有具体实例对象的类.抽象类有点类似“模板”的作用,目的是根据其格式来创建和修改新的类.对象不能由抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子 ...

  9. NHIBERNATE的简单框架的设计

    NHIBERNATE的简单框架的设计 上次的 NHibernate的Session管理策略和NHibernateHelper 发布并提供下载,给NHibernate刚入门的同学们带来很多便利. 最近有 ...

  10. 原生Js封装的弹出框-弹出窗口-页面居中-多状态可选

    原生Js封装的弹出框-弹出窗口-页面居中-多状态可选   实现了一下功能: 1.title可自定义 可拖拽 2.width height可以自定义 3.背景遮罩和透明度可以自定义 4.可以自己编辑弹出 ...