说说PHP中foreach引用的一个坑

From: http://blog.csdn.net/yipiankongbai/article/details/45307767

先来看看下面这段代码:

<?php
    $arr = array(‘apple‘,‘banana‘,‘cat‘,‘dog‘);
    foreach($arr as $key=>$val)
    {
        //some code
    }

    echo $val;  //输出dog
    echo $key;  //输出3

    //下面对val进行赋值
    $val = ‘e‘;
    print_r($arr);  //输出Array ( [0] => apple [1] => banana [2] => cat [3] => dog )

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

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

再来看看下面一段在foreach中使用引用的代码,这是最近在项目中遇到的一种情况:

<?php
    $arr = array(‘apple‘,‘banana‘,‘cat‘,‘dog‘);
    //在foreach中使用引用
    foreach($arr as $key => &$val)
    {
        $val = ‘new value‘;
    }

    echo $val;  //输出new value
    echo $key;  //输出3

    $val = ‘egg‘;
    print_r($arr);  //输出Array ( [0] => new value [1] => new value [2] => new value [3] => egg )

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

这种情况下很容易犯的错误就是像上面例子所示,在循环外面继续使用被foreach引用的变量,这样会使开发者得不到预期的数据。因此,为了避免这种情况的发生,应该在适当的位置释放变量的引用。以上面的代码为例:

<?php
    $arr = array(‘apple‘,‘banana‘,‘cat‘,‘dog‘);
    //在foreach中使用引用
    foreach($arr as $key => &$val)
    {
        $val = ‘new value‘;
    }
    unset($val);

    echo $val;  //报错,Notice: Undefined variable: val
    echo $key;  //输出3

    $val = ‘egg‘;
    print_r($arr);  //输出Array ( [0] => new value [1] => new value [2] => new value [3] => new value ) 在foreach结束后unset $val,此时会释放对$val的引用。因此改变$val不会对$arr造成影响。

这是最近在项目中遇到的坑和解决方案的总结,如果错误或更好地建议,欢迎指出。

原文地址:http://www.aintnot.com/2015/04/25/talk-about-a-hole-in-php-foreach-quote/

时间: 2024-10-19 15:40:48

说说PHP中foreach引用的一个坑的相关文章

mysql迁移到mongodb shared架构的过程中踩到的一个坑

Mysql库中有一个表,数据量在10亿左右,基本上对于这个表的操作都是没有意义的,因此想测试一下迁移到mongodb的shared架构上是否会有所改善.于是哼哧哼哧的搭建了一个3分片的mongo环境,并将mysql中这个大表的数据导出成了csv的格式,最终使用mongoimport工具成功将10亿多的数据导入mongo集群中去.但是导完后查看了下mongodb中对应的db的信息,差点没吓出尿来,请看: ## 在mongos中查看db的信息,显示迁移后的lens_mobapp_trace库大小为1

OpenStack Heat template中类型定义的一个坑

最新的Heat template目前支持string | number | json | comma_delimited_list | boolean等类型. 采用默认的hot格式,yaml文件格式. 定义一个string类型的属性,内容为true或false的时候,会报错. 查看heat engine的log会发现这个属性值默认被转为了boolean类型. 这是为何呢? 查看heat的代码,heat是调用的yaml库来直接load文件的,而对于yaml语言来说,如下的字符串都会被解析为bool

微信分享配置回调Activity中launchMode=&quot;singleInstance&quot;的一个坑

在做微信分享的时候,需要用到一个微信的回调Activity:WXEntryActivity 需要用到微信的jar包,可以去开放平台获取 public class WXEntryActivity extends BaseActivity implements IWXAPIEventHandler { 这个activity需要实现一个接口,接口回调函数 // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法 @Override public void onResp(BaseResp res

java中变量命名和引用变量的一个坑

这次有两个主题,第一个太简单啦,就是java中变量的命名规则,纯记忆性东西.第二个主题,就是讨论一下对象引用变量的一个注意点. 如果你对命名规则很熟啦,就直接看第二个内容吧.(上边的图稍微有点顺序紊乱啊) 一.java中变量的命名规则 大多数语言的命名规则是相似的,只有一些微小的差别. 变量的第一个位置,可以是字母,下划线(_),美元符($) (这个在c/c++,python中是不行的)(注意:不能是数字哦,一想就知道啦为什仫) 其他的位置可以是数字,字母,下划线 不能使用java中的关键字 j

PHP中逻辑运算符and/or与||/&amp;&amp;的一个坑

我原来以为PHP中的and和&&是一样的, 只是写法上为了可读性和美观, 事实上我错了. 这里面深藏了一个坑! 看以下代码: $bA = true; $bB = false; $b1 = $bA and $bB; $b2 = $bA && $bB; var_dump($b1); // $b1 = true var_dump($b2); // $b2 = false $bA = false; $bB = true; $b3 = $bA or $bB; $b4 = $bA ||

php中引用&amp;的一个小实例

在百度知道上碰到一段关于php的引用符&的代码,对于初学都来说还是很考验理解分析能力的,把代码和自己的分析贴上来作一个备份,也与大家共勉. 代码片段: 1 $arr =array(1,2,3,4); 2 foreach ($arr as $k =>&$v) {} 3 foreach ($arr as $k=>$v) {} 4 print_r($arr); 输出结果: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 3

PHP中的一个”坑“

说一个极有可能在工作中遇到的问题——foreach的引用 $arr = range(1,3); //[1,2,3] foreach($arr as &$val) { } foreach($arr as $val) { } print_r($arr); 上面这段代码输出什么呢,神奇的竟然是下面这样,这个我在工作中遇到过一次,当时弄了半天没弄出个所以然,只是找到了解决办法,这个问题解决办法有两个: Array ( [0] => 1 [1] => 2 [2] => 2 ) 下面这两种方

如何定义一个命令的别名,如何在命令中引用另一个命令的执行结果? &nbsp;

1.命令别名:alias alias:显示当前shell进程所有可用的命令别名 alias NAME="VALUE":命名别名 注意:在命令行中定义的别名,仅对当前shell进程有效,如果想永久有效,要定义配置文件 仅对当前用户:~/.bashrc 对所有有效:/etc/bashrc 2. 使用管道命令 | COMMAND1 | COMMAND2 | COMMAND3 |... 最后一个命令会在当前shell进程的子shell进程中执行: 如何定义一个命令的别名,如何在命令中引用另一个

openlayer关于feature中的一个坑

在Openlayer中使用Feature时候,有时候我们需要使用图片来做Maker,今天就讲我在这碰到的一个坑. 这一个除了黄色部分其他部分透明的png图片. 将其加入地图中后. 我们要注册一个Feature的Select事件. 结果,点击中间透明部分时,竟然没有信息提示,只有点击黄色部分时候才有提示!这不科学!!! 后来,为了证明是不是图片中间透明的原因.我请美工妹妹帮我弄了另一张图. 就是它了.替换图片后,结果是点击圆里都行!这不科学啊! 好了,这是一个坑,写下来纪念. 有关于openlay