복붙노트

foreach의 이상한 행동

PHP

foreach의 이상한 행동

<?php
  $a = array('a', 'b', 'c', 'd');

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

  print_r($a);
?>

나는 그것이 정상적인 프로그램이라고 생각하지만 이것은 내가 얻는 결과이다.

Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => c
)

누군가 제게 이것을 설명해 주시겠습니까?

해결법

  1. ==============================

    1.이것은 잘 문서화 된 PHP 동작입니다. php.net의 foreach 페이지에있는 경고를 보라.

    이것은 잘 문서화 된 PHP 동작입니다. php.net의 foreach 페이지에있는 경고를 보라.

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

    편집하다

    실제로 여기서 일어나는 일에 대한 단계별 가이드 시도

    $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'.
    
  2. ==============================

    2.첫번째 foreach 루프는 우리가 예상했던 것처럼 배열을 변경하지 않습니다. 그러나 $ v가 $ a 요소 각각에 대한 참조를 할당하게하므로, 따라서 첫 번째 루프가 끝날 때까지 $ v는 사실 $ a [2]에 대한 참조입니다.

    첫번째 foreach 루프는 우리가 예상했던 것처럼 배열을 변경하지 않습니다. 그러나 $ v가 $ a 요소 각각에 대한 참조를 할당하게하므로, 따라서 첫 번째 루프가 끝날 때까지 $ v는 사실 $ a [2]에 대한 참조입니다.

    두 번째 루프가 시작 되 자마자 $ v에 각 값이 할당됩니다. 요소. 그러나 $ v는 이미 $ a [2]에 대한 참조입니다. 따라서 모든 값 그것에 할당 된 코드는 자동으로 배열의 마지막 요소에 복사됩니다!

    따라서 첫 번째 반복 동안 $ a [2]는 0이되고, 다음에는 1이되고, 다시 한 번, 효과적으로 그 자체에 복사됩니다. 이 문제를 해결하기 위해 foreach에 의해 참조로 사용하는 변수를 항상 해제해야합니다. 루프를 사용하거나 더 나은 방법으로 전자를 모두 사용하지 마십시오.

  3. from https://stackoverflow.com/questions/4969243/strange-behavior-of-foreach by cc-by-sa and MIT license