V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ovear
V2EX  ›  PHP

关于PHP FOREACH的一个问题

  •  
  •   ovear · 2013-09-07 21:52:45 +08:00 · 4220 次点击
    这是一个创建于 4103 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <?php
    $ww = array(123,456,789);
    $qq = array(1,2,3);


    foreach ($ww as &$v) {}

    foreach ($qq as $v) {}

    print_r ($ww);
    print_r ($qq);

    ?>

    这段代码结果是

    Array ( [0] => 123 [1] => 456 [2] => 3 ) Array ( [0] => 1 [1] => 2 [2] => 3 )

    为什么 $ww[2]会变成3呢
    14 条回复    1970-01-01 08:00:00 +08:00
    GordianZ
        1
    GordianZ  
    MOD
       2013-09-07 21:58:54 +08:00   ❤️ 1
    http://php.net/manual/en/control-structures.foreach.php

    Warning
    Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
    mengzc
        2
    mengzc  
       2013-09-07 23:14:15 +08:00
    @GordianZ 能不能通俗点啊?我试验了半天,还不是很清楚。
    bixuehujin
        3
    bixuehujin  
       2013-09-07 23:27:32 +08:00
    第一个foreach结束后$v还可以访问,而且是$ww[2]的引用,第二个foreach每循环一次$ww[2]就被重写一次。

    所以最后$ww[2]值为3
    mengzc
        4
    mengzc  
       2013-09-07 23:57:21 +08:00
    现在知道了~~foreach ($qq as $v) {}
    这个运行完以后吧$v的值变了,所以 $ww[2]会变成3。
    如果你把两个foreach,更换顺序,结果就不一样咯,但是实际上还是把值变了,只是两个值一样。
    mengzc
        5
    mengzc  
       2013-09-08 00:06:24 +08:00
    @bixuehujin 为什么改变$v的值会把$ww[2]的值改变呢?
    osinx
        6
    osinx  
       2013-09-08 00:28:02 +08:00
    两行foreach之间加再加一句 
    unset($v);

    再看看执行的结果。
    msg7086
        7
    msg7086  
       2013-09-08 00:55:47 +08:00
    @mengzc 因为$v引用了$ww数组的最后一个元素。

    楼主文中的
    》foreach ($ww as &$v) {}

    》$v = &$ww[2];
    等效。
    而后的
    》foreach ($qq as $v) {}

    》$v = $qq[2];
    以及
    》$ww[2] = $qq[2];
    等效。

    不知能不能明白?
    anewg
        8
    anewg  
       2013-09-08 09:28:01 +08:00
    1楼早已给出答案,楼主要是懒得看英文,手册里有选项“view this page in”直接选中文就好了。

    “数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。”

    你要是foreach中用了&,则 foreach ($ww as &$v){} 中的$v(第一个foreach结束后$v引用在$ww的最后一个元素,也就是$ww[2]上)

    在之后的foreach中仍然是可以访问到$v($ww[2])的。而且不仅仅是foreach,只要你在之后的脚本中对$v赋值,都是会间接改变你的$ww[2](效果跟$v = &$ww[2]是一样的)

    所以你foreach里要是使用了引用,foreach结束后用unset($v);清除对 $ww[2] 的引用,消除后续语句对$ww[2]的影响.(楼主也可以改变你的第二个foreach为foreach ($qq as $q){},这样就没有使用到$v了)
    lvni
        9
    lvni  
       2013-09-08 11:03:28 +08:00
    第一个循环结束之后
    foreach ($ww as &$v) {}

    $v是指向$ww 最后一个值的引用

    此时如果对 $v 赋值都会改变 $ww 最后一个元素的值
    例如 :$v = 'someValue';
    则:
    $ww = Array
    (
    [0] => 123,
    [1] => 456,
    [2] => 'someValue'
    )

    第二个循环遍历逐个将 $qq 的元素赋值给 $v;
    循环结束时刚好是 $v = $qq[2] = 3
    lizheming
        10
    lizheming  
       2013-09-08 12:15:09 +08:00
    bombless
        11
    bombless  
       2013-09-08 13:25:50 +08:00
    引用的问题。一个很常见的坑。

    前一个foreach的最后一个循环使得$v指向$ww[2],后一个foreach的每一次循环把$qq中的值赋给这里的$ww[2]了
    picasso250
        12
    picasso250  
       2013-09-13 11:12:58 +08:00
    楼主试试以下几种情况,及其区别。

    1. 原来的这种
    foreach ($ww as &$v) {}
    foreach ($qq as $v) {}

    2. 只需要改个名字,bug就没有了
    foreach ($ww as &$vv) {}
    foreach ($qq as $v) {}

    3. 换个顺序也可以哦
    foreach ($qq as $v) {}
    foreach ($ww as &$v) {}

    4. 其实去掉引用符号就可以了
    foreach ($ww as $v) {}
    foreach ($qq as $v) {}

    5. 当然,官方一点的做法是
    foreach ($ww as &$v) {}
    unset($v)
    foreach ($qq as $v) {}

    请对照这些,实验,并且思考。直到自己领悟。

    (实话说吧,楼主的当务之急是学英语,学好了英语,这些问题的答案都在php官方手册上摆着呢)
    ovear
        13
    ovear  
    OP
       2013-09-14 14:37:05 +08:00
    @picasso250 =。=英文我倒是没问题,但是搜索引擎用的是中文。英文搜索的关键词完全不会。
    官方文档是个好东西,之前还没搜到。。
    ovear
        14
    ovear  
    OP
       2013-09-14 14:39:15 +08:00
    @anewg TAT,我之前看到了。。就直接感谢了回复者。。V2EX问题解决后需要回复还是关贴?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   973 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:47 · PVG 06:47 · LAX 14:47 · JFK 17:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.