1) Czy gdy tablica jest przekazywana jako argument do metody lub funkcji, jest przekazywana przez odwołanie lub wartość?
2) Czy podczas przypisywania tablicy do zmiennej nowa zmienna jest odniesieniem do oryginalnej tablicy, czy jest to nowa kopia?
Co z tym zrobić:
$a = array(1,2,3);
$b = $a;
Czy $b
jest odniesienie do $a
?
Odpowiedzi:
Druga część twojego pytania znajduje się na stronie tablicy podręcznika , która stwierdza (cytowanie) :
I podany przykład:
W pierwszej części najlepszym sposobem, aby się upewnić, jest spróbować ;-)
Rozważ ten przykład kodu:
Daje to wynik:
Co oznacza, że funkcja nie zmodyfikowała tablicy „zewnętrznej”, która została przekazana jako parametr: jest przekazywana jako kopia, a nie odwołanie.
Jeśli chcesz, aby przekazywana była przez referencję, musisz zmodyfikować funkcję w ten sposób:
I wynik będzie:
Ponieważ tym razem tablica została przekazana „przez odniesienie”.
Nie wahaj się przeczytać sekcji Objaśnienia do podręcznika w podręczniku: powinien on odpowiedzieć na niektóre pytania ;-)
źródło
&
, tak, powinno - patrz php.net/manual/en/…W odniesieniu do pierwszego pytania tablica jest przekazywana przez odniesienie, JEŚLI nie jest modyfikowana w wywoływanej metodzie / funkcji. Jeśli spróbujesz zmodyfikować tablicę w ramach metody / funkcji, najpierw tworzona jest jej kopia, a następnie modyfikowana jest tylko kopia. To sprawia, że wydaje się, że tablica jest przekazywana przez wartość, podczas gdy w rzeczywistości tak nie jest.
Na przykład, w tym pierwszym przypadku, nawet jeśli nie definiujesz swojej funkcji, aby akceptowała $ my_array przez referencję (przez użycie znaku & w definicji parametru), nadal jest przekazywana przez referencję (tj .: nie marnujesz pamięci z niepotrzebną kopią).
Jeśli jednak zmodyfikujesz tablicę, najpierw tworzona jest jej kopia (która zużywa więcej pamięci, ale nie zmienia oryginalnej tablicy).
FYI - jest to znane jako „leniwa kopia” lub „kopiowanie przy zapisie”.
źródło
TL; DR
a) metoda / funkcja odczytuje tylko argument tablicy => niejawne (wewnętrzne) odniesienie
b) metoda / funkcja modyfikuje argument tablicy => wartość
c) argument metody / funkcji tablicy jest wyraźnie oznaczony jako odwołanie (ze znakiem ampersand) => wyraźne odniesienie (user-land)
Lub to:
- parametr niezamienny i tablicowy : przekazany przez referencję; operacje zapisu zmieniają nową kopię tablicy, która jest tworzona przy pierwszym zapisie;
- parametr ampersand array : przekazany przez odniesienie; operacje zapisu zmieniają oryginalną tablicę.
Pamiętaj - PHP wykonuje kopiowanie wartości w momencie, gdy piszesz do parametru nie będącego znakiem ampersand. To
copy-on-write
znaczy. Chciałbym pokazać Ci źródło tego zachowania, ale tam jest przerażające. Lepiej użyj xdebug_debug_zval () .Pascal MARTIN miał rację. Kosta Kontos był jeszcze bardziej.
Odpowiedź
To zależy.
Długa wersja
Myślę, że zapisuję to dla siebie. Powinienem mieć blog czy coś ...
Ilekroć ludzie mówią o referencjach (lub wskaźnikach, jeśli o to chodzi), zwykle kończą się logomatyką (wystarczy spojrzeć na ten wątek !).
PHP jako czcigodny język, pomyślałem, że powinienem dodać do zamieszania (choć jest to streszczenie powyższych odpowiedzi). Ponieważ chociaż dwie osoby mogą mieć rację w tym samym czasie, lepiej po prostu połamać sobie głowy w jedną odpowiedź.
Po pierwsze, powinieneś wiedzieć, że nie jesteś pedantem, jeśli nie odpowiadasz w czarno-biały sposób . Sprawy są bardziej skomplikowane niż „tak / nie”.
Jak zobaczysz, cała rzecz według wartości / referencji jest bardzo związana z tym, co dokładnie robisz z tą tablicą w zakresie metody / funkcji: czy ją czy modyfikujesz?
Co mówi PHP? (alias „zmiany”)
Instrukcja mówi ten (mój nacisk):
O ile mi wiadomo, kiedy duzi, poważni, uczciwi programiści mówią o referencjach, zwykle mówią o zmianie wartości tych referencji . I to jest dokładnie to, co mówi o ręcznych:
hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.Jest jednak inny przypadek, o którym nie wspominają: co jeśli nic nie zmienię - po prostu przeczytaj?
Co się stanie, jeśli przekażesz tablicę metodzie, która nie oznacza jawnie odwołania, a my nie zmienimy tej tablicy w zakresie funkcji? Na przykład:
Czytaj dalej, mój towarzyszu podróży.
Co właściwie robi PHP? (aka „pod względem pamięci”)
Ci sami duzi i poważni programiści, kiedy stają się jeszcze poważniejsi, mówią o „optymalizacjach pamięci” w odniesieniu do referencji. Podobnie PHP. Ponieważ
PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
właśnie dlatego .Nie byłoby idealne przekazywanie OGROMNYCH tablic do różnych funkcji, a PHP tworzenie ich kopii (w końcu to właśnie robi funkcja „pass-by-value”):
Cóż, teraz, gdyby to była wartość przekazywana, nie byłoby już około 3 MB pamięci RAM, ponieważ istnieją dwie kopie tej tablicy, prawda?
Źle. Dopóki nie zmienimy
$arr
zmiennej, jest to odniesienie pod względem pamięci . Po prostu tego nie widzisz. Właśnie dlatego PHP wspomina o odniesieniach do ziemi użytkownika podczas&$someVar
rozróżniania wewnętrznych i jawnych (ze znakami ampersand).Fakty
Więc,
when an array is passed as an argument to a method or function is it passed by reference?
Wymyśliłem trzy (tak, trzy) przypadki:
a) metoda / funkcja odczytuje tylko argument tablicy;
b) metoda / funkcja modyfikuje argument tablicy;
c) argument metody / funkcji tablicy jest wyraźnie oznaczony jako odwołanie (za pomocą ampersand)
Po pierwsze, zobaczmy, ile pamięci faktycznie zjada tablica (uruchom tutaj ):
Tyle bajtów. Wspaniały.
a) metoda / funkcja odczytuje tylko argument tablicy
Stwórzmy teraz funkcję, która odczytuje tylko tę tablicę jako argument i zobaczymy, ile pamięci zajmuje logika odczytu:
Chcesz zgadnąć? Dostaję 80! Przekonaj się sam . Jest to część, którą omija podręcznik PHP. Jeśli
$arr
parametr rzeczywiście był przekazywany przez wartość, zobaczysz coś podobnego do1331840
bajtów. Wygląda na to, że$arr
zachowuje się jak odniesienie, prawda? To dlatego, że jest to odniesienie - wewnętrzne.b) metoda / funkcja modyfikuje argument tablicy
Teraz, niech pisze na tym param, zamiast czytać z niego:
Ponownie, przekonaj się sam , ale dla mnie jest to bardzo bliskie bycia 1331840. W tym przypadku tablica jest kopiowana
$arr
.c) argument tablicy metod / funkcji jest wyraźnie oznaczony jako odwołanie (ze znakiem ampersand)
Zobaczmy teraz, ile pamięci zajmuje operacja zapisu do jawnego odwołania (uruchom tutaj ) - zwróć uwagę na znak ampersand w podpisie funkcji:
Założę się, że otrzymasz maksymalnie 200! Więc zjada to w przybliżeniu tyle samo pamięci, co odczyt z paramperów i ampers .
źródło
Domyślnie
Tablice obiektów są przekazywane przez wartość (tablicę), ale każdy obiekt jest przekazywany przez odwołanie.
Uwaga: W ramach optymalizacji każda pojedyncza wartość jest przekazywana jako odniesienie, dopóki nie zostanie zmodyfikowana w funkcji. Jeśli zostanie zmodyfikowany, a wartość zostanie przekazana przez odwołanie, zostanie skopiowana, a kopia zmodyfikowana.
źródło
Kiedy tablica jest przekazywana do metody lub funkcji w PHP, jest przekazywana przez wartość, chyba że jawnie przekażesz ją przez referencję, na przykład:
W drugim pytaniu
$b
nie chodzi o odniesienie$a
, ale o kopię$a
.Podobnie jak w pierwszym przykładzie, możesz odwoływać
$a
się, wykonując następujące czynności:źródło
Ten wątek jest nieco starszy, ale tutaj właśnie się natknąłem:
Wypróbuj ten kod:
http://codepad.viper-7.com/gwPYMw
Uwaga: parametr $ params nie ma wzmacniacza, a mimo to zmienia wartość $ arr [„data”]. To tak naprawdę nie pasuje do wszystkich innych wyjaśnień tutaj i tego, co myślałem do tej pory.
Jeśli sklonuję obiekt $ params ['data'], druga wygenerowana data pozostanie taka sama. Jeśli po prostu ustawię go na ciąg znaków, nie wpłynie to również na wynik.
źródło
Aby rozszerzyć jedną z odpowiedzi, również podstrony tablic wielowymiarowych są przekazywane przez wartość, chyba że są przekazywane jawnie przez odwołanie.
Wynik to:
źródło
W PHP tablice są domyślnie przekazywane do funkcji domyślnie, chyba że jawnie przekazujesz je przez odwołanie, jak pokazuje następujący fragment:
Oto wynik:
źródło