php中foreach使用引用的陷阱
有时候我们为了在循环过程中改变数组项的值,在foreach的时候变量入口可以加个&符合,
表示,循环过程中使用数组中原来的值,而不是一个复制的值,如
foreach ($array as &$item) {}
这样一来,我们在循环中修改$item的值的时候,实际上修改的是$array中对应的值,
而如果不加&符号的话,在循环中修改$item的值不会影响到$array。
例子:
$array = [
'name' => 'Jobs',
'age' => 50,
]; foreach ($array as $key => $value) {
$value = 22;
}
print_r($array); foreach ($array as $key => &$value) {
$value = 22;
}
print_r($array);
Array
(
[name] => Jobs
[age] => 50
)
Array
(
[name] => 22
[age] => 22
)
陷阱:两次循环使用同样的临时变量的情况下,如果第一次循环使用的是引用,
那么在第二次循环中即使没有加&符号,临时变量也是引用。
这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。
例子:
$array = [
'name' => 'php',
'age' => 123,
]; foreach ($array as $key => &$value) {
echo "key=$key, value=$value" . PHP_EOL;
} foreach ($array as $key => $value) {
echo "key=$key, value=$value" . PHP_EOL;
}
key=name, value=php
key=age, value=123
key=name, value=php
key=age, value=php
上面最后一行的value是"php",并不是我们期望的123,这是因为,在第二个foreach循环中,
每一次循环的时候,都修改了$array中的key为'age'的值,
第一次循环的时候,数组中的age就已经是php(第一个值)了,在后续的循环中会依次改变数组中最后一个值,
到最后一次循环的时候,取得的值是prev($array),也就是php了。
如何避免这个问题?
1、在第二次循环之前,unset($value)
2、第二次foreach的时候使用不同名字的变量,如$item
另:查看一个变量是否是引用可以使用xdebug_debug_zval函数(需要有xdebug扩展)。
xdebug_debug_zval的结果形如:
value: (refcount=2, is_ref=1)=123
php中foreach使用引用的陷阱的更多相关文章
- PHP中foreach有关引用的问题
软件开发的过程中,细节处理非常重要,说得大一点就是细节决定成败,别人不懂的地方,你懂,别人没注意到的细节,你注意到了,这就是你胜出对方的地方,这样就体现出了你的价值. 下面是几个foreach循环中引 ...
- PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么?
PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么? 代码如下: <?php $arr = array('one','two','three'); fo ...
- JavaScript中forEach的用法相关
首先说下JavaScript的forEach的标准格式. 为数组中的每个元素执行指定操作. array1.forEach(callbackfn[, thisArg]) 参数 定义 array1 必需. ...
- PHP和Java中foreach循环的用法区别
1.foreach语句介绍: ①PHP: foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息. ...
- php中foreach源码分析(编译原理)
php中foreach源码分析(编译原理) 一.总结 编译原理(lex and yacc)的知识 二.php中foreach源码分析 foreach是PHP中很常用的一个用作数组循环的控制语句.因为它 ...
- C#中的线程之Abort陷阱
.简介 C#中通常使用线程类Thread来进行线程的创建与调度,博主在本文中将分享多年C#开发中遇到的Thread使用陷阱. Thread调度其实官方文档已经说明很详细了.本文只简单说明,不做深入探讨 ...
- Java 8 中的方法引用,轻松减少代码量,提升可读性!
1. 引言 Java8中最受广大开发中喜欢的变化之一是因为引入了 lambda 表达式,因为这些表达式允许我们放弃匿名类,从而大大减少了样板代码,并提高了可读性. 方法引用是lambda表达式的一种特 ...
- 『动善时』JMeter基础 — 40、JMeter中ForEach控制器详解
目录 1.什么是逻辑控制器 2.ForEach控制器介绍 3.ForEach控制器的使用 (1)测试计划内包含的元件 (2)获取学院列表请求内容 (3)JSON提取器内容 (4)ForEach控制器内 ...
- 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图
[源码下载] 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Co ...
随机推荐
- 洛谷【P1052】过河
https://www.luogu.org/problemnew/show/P1052 题目描述 在河上有一座长度为 L 的独木桥, 一只青蛙想沿着独木桥从河的一侧跳到另一侧. 在桥上有一些石子, 青 ...
- loadrunner socket协议问题归纳(5)
获取服务器的返回值,可以用web_reg_save_param函数,该参数最好放到: 语法: int web_reg_save_param(const char *ParamName, <lis ...
- 2016-6-2-第二个sprint
1.开始一个新的冲刺: 起止:2016.6.1~2016.6.14 ProductBacklog:继续向下细化 Sprint 计划会议:确定此次冲刺要完成的目标 Sprint Backlog:新的冲刺 ...
- Scrum立会报告+燃尽图(十月二十八日总第十九次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2288 项目地址:https://git.coding.net/zhang ...
- 2018软工实践—Alpha冲刺(3)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助后端界面的开发 搭建项目运行的服务器环境 ...
- Lucene 分词
在Lucene中很多数据是通过Attribute进行存储的 步骤是同过TokenStrem获取文本信息流 TokenStream stream = a.tokenStream("conten ...
- IE劫持
解析雅虎与百度流氓原理- 为什么“浏览器劫持”能够如此猖狂呢?放眼众多论坛的求助贴,我们不时可以看到诸如“我的IE被主页被改了,我用杀毒工具扫了一遍都没发现病毒,我把主页改回自己的地址,可是一重启它又 ...
- eclipse取消validation验证
点击按钮如下:window-Preferences-Validation.如图. 然后把build里面的都取消.即可.
- YARN中用的作业调度算法:DRF(Dominant Resource Fairness)
在Mesos和YARN中,都用到了dominant resource fairness算法(DRF),它不同于hadoop基于slot-based实现的fair scheduler和capacity ...
- 3dContactPointAnnotationTool开发日志(三四)
今天就是让背景图可以变大变小,变透明度,然后将3d的点投影到图片上,输出2d接触点信息: 可以看到输出了正确的接触点信息: 然后还把空物体的包围盒大小设置为边长为0.1的的正方体,点击选中 ...