Strange behavior Of foreach

前端 未结 2 1650
醉梦人生
醉梦人生 2020-11-22 03:39

I think it\'s a no

相关标签:
2条回答
  • 2020-11-22 04:01

    This is well-documented PHP behaviour See the warning on the foreach page of php.net

    Warning

    Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

    $a = array('a', 'b', 'c', 'd');
    
    foreach ($a as &$v) { }
    unset($v);
    foreach ($a as $v) { }
    
    print_r($a);
    

    EDIT

    Attempt at a step-by-step guide to what is actually happening here

    $a = array('a', 'b', 'c', 'd');
    foreach ($a as &$v) { }   // 1st iteration $v is a reference to $a[0] ('a')
    foreach ($a as &$v) { }   // 2nd iteration $v is a reference to $a[1] ('b')
    foreach ($a as &$v) { }   // 3rd iteration $v is a reference to $a[2] ('c')
    foreach ($a as &$v) { }   // 4th iteration $v is a reference to $a[3] ('d')
    
                              // At the end of the foreach loop,
                              //    $v is still a reference to $a[3] ('d')
    
    foreach ($a as $v) { }    // 1st iteration $v (still a reference to $a[3]) 
                              //    is set to a value of $a[0] ('a').
                              //    Because it is a reference to $a[3], 
                              //    it sets $a[3] to 'a'.
    foreach ($a as $v) { }    // 2nd iteration $v (still a reference to $a[3]) 
                              //    is set to a value of $a[1] ('b').
                              //    Because it is a reference to $a[3], 
                              //    it sets $a[3] to 'b'.
    foreach ($a as $v) { }    // 3rd iteration $v (still a reference to $a[3]) 
                              //    is set to a value of $a[2] ('c').
                              //    Because it is a reference to $a[3], 
                              //    it sets $a[3] to 'c'.
    foreach ($a as $v) { }    // 4th iteration $v (still a reference to $a[3]) 
                              //    is set to a value of $a[3] ('c' since 
                              //       the last iteration).
                              //    Because it is a reference to $a[3], 
                              //    it sets $a[3] to 'c'.
    
    0 讨论(0)
  • 2020-11-22 04:07

    The first foreach loop does not make any change to the array, just as we would expect. However, it does cause $v to be assigned a reference to each of $a’s elements, so that, by the time the first loop is over, $v is, in fact, a reference to $a[2].

    As soon as the second loop starts, $v is now assigned the value of each element. However, $v is already a reference to $a[2]; therefore, any value assigned to it will be copied automatically into the last element of the array!

    Thus, during the first iteration, $a[2] will become zero, then one, and then one again, being effectively copied on to itself. To solve this problem, you should always unset the variables you use in your by-reference foreach loops—or, better yet, avoid using the former altogether.

    0 讨论(0)
提交回复
热议问题