2010-12-29 25 views
12

Jaka jest różnica między

foreach ($my_array as $my_value) { 
} 

oraz:

foreach ($my_array as &$my_value) { 
} 

?

Czy mogę prosić o dwa rzeczywiste przykłady tego, kiedy należy z nich korzystać, a kiedy korzystać z drugiego?

+1

Jako zasada, nigdy nie używać referencji. – troelskn

+4

@troelskn: To głupia zasada. Czasami trzeba z nich korzystać. Jeśli nie wiesz, czy powinieneś ich używać, prawdopodobnie nie musisz tego robić. Ale kiedy chcesz zmodyfikować rzeczywistą wartość, musisz użyć referencji. –

+0

@Felix Kling: Zgadzam się z @troelskn. Nigdy nie miałem potrzeby modyfikowania rzeczywistej wartości tablicy. Za każdym razem, gdy musiałem, możesz zrobić znacznie ładniejszy kod niż przy użyciu ('& $ var'). Jedynym sposobem, jaki mogę wymyślić, może być ... optymalizacja: jeśli używasz "&", przypuszczam (popraw mnie, jeśli się mylę), że nie ma potrzeby tworzenia kopii w zmiennej tymczasowej. W ten sposób zysk czasu realizacji. Jeśli masz przykład, w którym nie możesz uniknąć pętli podobnych do tego z "&" w moim pytaniu, czy mogę prosić o pokazanie ich jako komentarza tutaj? Dziękuję Ci bardzo! –

Odpowiedz

21

Pierwszy przykład tworzy kopię wartości, a drugi używa odniesienia do wartości początkowej. Po pierwszym uruchomieniu foreach oryginalna tablica pozostaje nietknięta. Po drugim foreach oryginalna tablica mogła zostać zmodyfikowana, ponieważ była obsługiwana przez odniesienie.

Niektóre rodzime funkcje PHP już działają w ten sposób, na przykład shuffle(), które zmieniają układ macierzy. Zauważysz, że ta funkcja nie zwraca tablicę, po prostu nazwać:

$myArray = array('foo', 'bar', 'fizz', 'buzz'); 
shuffle($myArray); 
// $myArray is now shuffled 

I to działa jego magia, ponieważ współpracuje z tablicy przez odniesienie zamiast tworzenia kopii.

Następnie są funkcje, które nie przeszły niczego przez odniesienie ale raczej do czynienia z kopią oryginalnej wartości, takie jak ucwords() która zwraca nowy ciąg wynikowy:

$myString = "hello world"; 
$myString = ucwords($myString); 
// $myString is now capitalized 

Zobacz Passing by Reference.

+2

jeśli $ my_value jest obiektem, to nieuchronnie przeszedł przez odniesienie. – Epharion

+1

@Epharion: Nie, PHP zawsze przechodzi przez wartość val, chyba że przekazane jest przez referencję. A obiekty nie są wyjątkiem. Tylko z obiektami funkcja pass by val jest bardzo podobna do passa przez ref ze względu na sposób, w jaki PHP przechowuje obiekty;) – NikiC

5

Jonathan's answers opisuje to bardzo dobrze. Tylko dla kompletności, tu są twoje dwa przykłady:

  1. tylko odczyt wartości:

    $my_array = range(0,3); 
    foreach ($my_array as $my_value) { 
        echo $my_value . PHP_EOL; 
    } 
    
  2. dodając niektóre numer do każdego elementu (stąd modyfikujące każdą wartość):

    foreach ($my_array as &$my_value) { 
        $my_value += 42; 
    } 
    

    Jeśli nie używasz &$my_value, to dodanie nie będzie miało żadnego wpływu na $my_array. Ale można napisać te same referencje nie używając:

    foreach($my_array as $key=>$value) { 
        $my_array[$key] = $value + 42; 
    } 
    

    Różnica polega na tym, że mamy dostęp do/zmianie oryginalnej wartości bezpośrednio z $my_array[$key].

DEMO

+0

Dziękuję bardzo, twoje przykłady są jasne jak woda. –

0

Gdy prefiks zmiennej z ampersand, tworzysz „odniesienie”. Referencje PHP są skrótami lub dowiązania jak na komputerze. Możesz utworzyć zmienną wskaźnika, która jest po prostu inną nazwą dla tych samych danych.

Nie widzę dużej różnicy w ich użyciu, z wyjątkiem tego, że NIE KOPIUJ zmiennej pamięci. Podczas przekazywania zmiennych można po prostu przekazać referencje i punkty odniesienia do oryginalnego obiektu.

+0

Typowy błąd początkującego: myśleć, że PHP jest głupi. PHP nie ślepo kopiuje wartości. Wykorzystuje koncepcję kopiowania przy zapisie, tzn. Że wartość jest tylko kopiowana, gdy jest zmieniana. Tworzenie odwołań ze względu na wydajność zwykle ma jedynie charakter przeciwny do zamierzonego, ponieważ często powoduje, że PHP wykonuje tylko więcej kopii. – NikiC

0

Prawdziwy przykład światowym & stosowania jest, gdy trzeba zmienić zawartość tablicy z niewielu linii kodu

foreach($arrFeed as &$objFeed) 
    $objFeed['externalSrc'] = convertToLocalImage($objFeed['externalSrc']); 
Powiązane problemy