PHP关于foreach使用引用变量的坑
写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]
解决办法:
- 尽量不使用相同的循环变量名;
- 每次使用完或再次使用前进行 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使用引用变量的坑的更多相关文章
- 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 ...
- 【PHP】 foreach循环中变量引用的一道面试题
$a = array('a','b','c'); foreach($a as &$v){} foreach($a as $v){ } var_dump($a); 现在.不要打开浏览器,猜测一下 ...
- PHP使用引用变量foreach时,切记其他循环不要使用同一个名字的变量
foreach ($log['data'] as $k => &$value) { if ($value['token'] != 0) { $value['change_num'] = ...
- 引用变量 php面试总结1
(1)PHP引用变量 概念:不同的变量名,访问同一个变量内容,使用& 知识点: 使用php函数 (a)memory_get_usage() 查看内存使用情况 eg // 定义一个变量 $a = ...
- php中foreach使用引用的陷阱
有时候我们为了在循环过程中改变数组项的值,在foreach的时候变量入口可以加个&符合, 表示,循环过程中使用数组中原来的值,而不是一个复制的值,如 foreach ($array as &a ...
- PHP面试 PHP基础知识 一(引用变量)
PHP引用变量 常见引用变量面试题: 什么是引用变量? 在PHP中用什么符号定义引用变量? 考点:PHP的引用变量的概念及定义方式 概念:在PHP中引用意味着用不用的名字访问同一个变量内容 定 ...
- Java基础-被final修饰的引用变量的指向
final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象,那么该引用变量指向的对象的内容可变吗?看下面这个例子: public class Test { public static void ...
- PHP GC垃圾回收机制之引用变量回收周期疑问
普通的引用变量的销毁大家都知道, 当unset的时候如果refcount = 0 则认为无用, 销毁. 但是手册中提到一点会有递归引用的问题,很是奇葩 代码如下 <?php $a = 1; $a ...
- C++引用变量(转)
引用变量 c++中引用变量的使用: 定义: int rate=80; int & pt=rate 1.pt 是引用变量,申明引用变量时必须将其初始化.pt 和rate 的值指向相同的内存变量 ...
随机推荐
- [译]Java设计模式之解释器
(文章翻译自Java Design Pattern: Interpreter) 解释器模式适用于当一些内容需要翻译的时候.下面的例子是一个非常简单的解释器实现.它将字母"a"和&q ...
- android JBOX2D粒子碰撞的实例,以达到特殊效果
最近完成动画特效工作的一个发展.的效果,所以传统的三大动画无法满足咱们的需求啦(事实上这不是一个动画效果的议题.事实上有一点点游戏的感觉). 寻找一个粒子系统吧,发现JBox2D比較简单的能满足咱们 ...
- 安卓推送——个推服务端api使用误区
首先你需要在个推开放着平台上注册你的应用,以及获得以下几个必要的值APPID |APPKEY | MASTERSECRET,本文假设你已经完成上述步骤以及完成客户端SDK的集成. 原理 个推服务端ap ...
- glibc-2.19 之 strlen 实现
前几天遇到一个有意思的问题,实现strlen 不考虑线程安全: 下面是我的实现: size_t strlen(const char* s) { const char* p = s; while (*p ...
- Java泛型学习笔记--Java泛型和C#泛型比较学习(一)
总结Java的泛型前,先简单的介绍下C#的泛型,通过对比,比较学习Java泛型的目的和设计意图.C#泛型是C#语言2.0和通用语言运行时(CLR)同时支持的一个特性(这一点是导致C#泛型和Java泛型 ...
- 苹果推送通知服务Push Notification探究总结(序)
刚才发了两篇几个月前写的文档,觉得太敷衍了,想了想,还是来一发实在的. 再者,刚好上周研究了苹果的推送通知服务Push Notification,还是很有心得的,赶紧趁热打铁,记录一下,望与大家谈论下 ...
- C/C++基础知识总结——数组、指针域、字符串
1. 数组 1.1 数组作为函数参数 (1) 如果使用数组作为函数的参数,则实参和形参都是数组名,且类型要相同.数组名做参数时传递的是地址 (2) 使用方法: void rowSum(int a[][ ...
- 关于 HttpModule配置问题
在经典模式下,配置到System.web节点 在IIS7以上的集成模式下,要配置到<system.webServer>节点 否则会出现类似一下的错误: 具体配置如下: <config ...
- 关于iOS UIScrollView放大的问题
总所周知 ,iOS 的UIScrollView是专门用来做缩放和分页用的,关于这方面的例子也很多了,但你们知道在放大的过程中 他做了些什么吗? 他的哪些东西会发生改变吗? 通过在一个项目中的小经历 ...
- 搜索广告与广告网络Demand技术-探索与利用
探索与利用(Explore and exploit) 点击率预测中还有一个重要的问题,就是探索与利用,它在工程中解决的并不好,我这章把现在论文中的常见的几种方法介绍一下.探索与利用它是所有互联网应用都 ...