2011-02-11 23 views
28
<?php 
    $a = array('a', 'b', 'c', 'd'); 

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

    print_r($a); 
?> 

myślę, że to normalny program, ale to jest wyjście otrzymuję:dziwne zachowanie foreach

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

Czy ktoś mógłby mi to wyjaśnić?

+4

Co "* myślę, że jest to normalny prog, ale internet widziałem op ......... wtedy ... ahh wat to jest" * znaczy? –

+0

Zastanawiam się !!! Dlaczego uzyskać ten wynik? :) –

+1

@Bart Kiers: Wygląda na oszołomionego. – BoltClock

Odpowiedz

67

Jest to dobrze udokumentowane zachowanie PHP Zobacz warning na stronie foreach z php.net

Ostrzeżenie

referencyjnej wartości $ i ostatniego elementu tablicy pozostają jeszcze po pętli foreach. Zalecane jest zniszczenie go przez unset().

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

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

print_r($a); 

EDIT

Próba przewodnikiem krok po kroku do tego, co się rzeczywiście dzieje tutaj

$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

Wiem to !!! Ale co jest nie tak w moim programie? –

+3

@Manish Trivedi: Zobacz część ** Ostrzeżenie **, dlaczego tak się dzieje. Nie ma nic złego w twoim programie. – BoltClock

+0

Dzięki ..... mam to –

2

Pierwsza pętla foreach nie ma żadnych zmian do array, tak jak byśmy oczekiwali. Powoduje to jednak, że $v ma przypisane odniesienie do każdego z elementów $a, , tak że w momencie zakończenia pierwszej pętli $v jest w rzeczywistości odniesieniem do $a[2].

Po uruchomieniu drugiej pętli $v jest teraz przypisywany do wartości każdego elementu . Jednak $v jest już odniesieniem do $a[2]; dlatego każda przypisana mu wartość zostanie automatycznie skopiowana do ostatniego elementu tablicy!

Zatem podczas pierwszej iteracji, $a[2] będzie zero, jeden, a następnie jeden raz, jest skutecznie skopiowane do siebie. Aby rozwiązać ten problem, należy zawsze odłączyć zmienne używane w odsyłaczach od jednego do drugiego, lub, jeszcze lepiej, unikać używania tego pierwszego.