`
zccst
  • 浏览: 3322483 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

foreach在引用时的陷阱

    博客分类:
  • PHP
 
阅读更多
这个陷阱在PHP里存在很久了,先看代码:

<?php
$array = array(1, 2, 3);

foreach ($array as &$v) {}
foreach ($array as  $v) {}

print_r($array);
?>

运行代码,得到的结果却是:
Array
(
[0] => 1
[1] => 2
[2] => 2
)可以发现,经过两次foreach后,最后一个元素由3变成了2。

为什么会这样呢?这是因为第一次foreach的时候$v成为了一个引用变量($array[2]),如此,当第二次foreach的时候,实际上只是在对这个引用变量($array[2])进行了若干次赋值而已。

第一次:$array[2] = 1,此时$array各元素分别为1,2,1
第二次:$array[2] = 2,此时$array各元素分别为1,2,2
第二次:$array[2] = 2,此时$array各元素分别为1,2,2

一不小心很可能会掉入这个陷阱,为了避免这个问题,需要在第一次foreach后执行unset($v),解决方案有点丑陋,但也没有办法,PHP脚本里的变量一旦生成就在整个脚本中有效,不像Java中,变量是块级别的,仅仅在对应的{}中有效。

PHP的Bug系统里能看到关于这个这个问题的链接,不过从04年提出这个问题到现在已经四年了,估计PHP团队不会解决这个问题了。也是,从PHP的脚本特性来说这也可以说不是Bug,只是苦了我们这些程序员,要多加小心了。
分享到:
评论

相关推荐

    浅谈PHP中关于foreach使用引用变量的坑

    然而,当我们在`foreach`循环中使用引用变量时,可能会遇到一些陷阱,导致意料之外的结果。本文将深入探讨这个问题,并提供解决方案。 首先,我们要理解PHP中的引用。在PHP中,引用并不是创建了一个新变量,而是让...

    php foreach 使用&amp;(与运算符)引用赋值要注意的问题

    在上述例子中,作者通过两个数组($arr和$arr2)演示了在foreach循环中使用引用的可能陷阱。第一个foreach循环向数组元素添加字符串"4"。如果没有在循环后断开引用,那么第二个foreach循环遍历第二个数组($arr2)时,...

    探讨:php中在foreach中使用foreach ($arr as &amp;$value) 这种类型的解释

    当我们在`foreach`循环中使用`foreach ($arr as &$value)`这样的语法时,我们实际上是在以引用的方式处理数组元素,而非简单的值复制。本文将深入探讨这种用法的原理、优缺点以及适用场景。 首先,理解引用的概念至...

    JavaScript性能陷阱小结(附实例说明)

    JavaScript性能优化是每个开发者在编写高效代码时必须关注的关键领域。由于JavaScript的动态特性,一些编程习惯可能导致不必要的性能损耗。以下是一些常见的JavaScript性能陷阱及其优化建议: 1. **避免使用`eval`...

    PHP程序设计-3期(KC016) 2.7.3数组遍历常见问题.docx

    - 使用`foreach`遍历数组时,可以获取当前元素的键和值,但要注意不要混淆数组的引用和复制。 - 如果数组可能为空,应在循环前检查其长度,以防止空数组导致的错误。 通过理解这些常见问题和解决方案,你可以更...

    net gotachas

    .NET Gotchas是一个广泛使用的术语,指的是在开发.NET应用程序时可能会遇到的陷阱或意外情况。这些gotchas通常是由于对.NET框架不完全理解或者某些隐藏的行为所导致的问题。在深入探讨.NET Gotchas之前,让我们先...

    PHP PDOStatement:bindParam插入数据错误问题分析

    在这种情况下,通过在foreach中使用引用符号"&",确保每次迭代时,bindParam都得到正确的变量引用。但这种方法容易引起混淆,不建议在一般情况下使用。 总之,理解bindParam的工作机制至关重要,特别是它对引用...

    突破程序员基本功的16课.part2

    6.6 foreach循环的循环计数器 6.7 小结 第7课 面向对象的陷阱 7.1 instanceof运算符的陷阱 7.2 构造器的陷阱 7.2.1 构造器之前的void 7.2.2 构造器创建对象吗 7.2.3 无限递归的构造器 7.3 持有当前类的实例...

    【03-流程控制与数组】

    •当使用foreach循环来迭代输出数组元素或集合时,通常不要对循环变量进行赋值,虽然这种赋值在语法上是允 许的,但没有太大的意义,而且极容易引起错误。 深入数组 •数组元素和数组变量在内存里是分开...

    使用HSSF、XSSH操作Excel数据时遇到的一些问题

    - **问题**:公式计算可能在读取或写入时出错,特别是在处理跨表引用和复杂公式时。 - **解决**:使用`FormulaEvaluator`类来评估公式,确保公式在写入前正确计算,同时注意跨表引用的处理。 5. **行和列的遍历**...

    microsoft.net gotchas

    使用`foreach`循环时,系统会自动管理枚举器的生命周期,但手动创建枚举器时需谨慎。 4. **资源管理**:非托管资源(如文件句柄、数据库连接等)必须正确释放,以防止内存泄漏。使用`using`语句可以简化资源清理。 ...

    错误剖析之JavaScript的9个陷阱及评点

    为了解决这个问题,可以在`ClickHandler`内部使用一个变量(例如`self`)来保持对`MyObject`实例的引用。 **评点**:理解`this`的作用域对于避免此类陷阱至关重要。此外,现代JavaScript提供了箭头函数等特性,它们...

    apache velocity介绍及资料

    在使用Velocity时,你需要创建一个Velocity上下文(Context),在这个上下文中添加你想要在模板中访问的对象。然后,通过Velocity模板引擎将这个上下文和模板文件合并,生成最终的输出。Velocity引擎会自动处理对象的...

    动态循环给onclick赋值(解决闭包问题)

    然而,由于JavaScript的异步性质和作用域链机制,循环结束时,所有事件处理函数都将引用同一个循环变量的最终值,而不是它们在循环中的各自值。这就是所谓的闭包问题。 要解决这个问题,有几种常见的方法: 1. **...

    effective c sharp

    3. **利用`yield return`进行迭代**:在C#中,`yield return`允许在遍历集合时创建一个迭代器,无需一次性计算所有元素,从而提高性能和内存效率。 4. **理解`null`和`Nullable&lt;T&gt;`**:C#中的`null`是引用类型的...

    Windows PowerShell in Action Errors, Updates and Clarifications

    - **Chapter 12**:自动化任务时的常见陷阱。 - **Chapter 13**:安全性和权限方面的错误指导。 - **附录错误**:对附录中可能存在的错误进行说明。 - **读者问题解答与附加材料** - **评论语法在 PowerShell ...

    提高C#编程水平不可不读的50个要诀.txt

    反射允许在运行时检查和修改对象的结构和行为,但在频繁使用时可能导致性能下降。应谨慎使用反射,仅在必要时采用,并考虑其对性能的影响。 #### 25. 模块化设计,遵循单一职责原则 将程序分解为多个独立的模块,...

    jdk1.8_api_ch.zip

    10. **Type Annotations**:Java 8增加了类型注解,可以在类型使用的地方(如参数、返回值、字段等)添加注解,用于编译时或运行时的类型检查。 以上这些特性使得Java 8在功能、性能和开发体验上都有了显著提升,...

    Velocity用户手册---中文版

    4. **模板语法**:包括变量引用($var)、占位符(#{expr})、条件语句(#if, #else, #elseif)、循环结构(#foreach)以及宏定义和调用等。 5. **Struts与Velocity的集成**:Struts是一个MVC框架,而Velocity是...

Global site tag (gtag.js) - Google Analytics