TL; DR
a) yöntem / işlev yalnızca dizi bağımsız değişkenini okur => örtük (iç) başvuru
b) yöntem / işlev dizi bağımsız değişkenini değiştirir => değer
c) yöntem / işlev dizi bağımsız değişkeni açıkça bir başvuru işareti olarak işaretlenir (ve işareti ile) => açık (kullanıcı-arazi) referansı
Veya bu:
- ve işareti olmayan dizi parametresi : referans ile geçti; yazma işlemleri dizinin yeni bir kopyasını değiştirir, kopya ilk yazmada oluşturulur;
- ve işareti dizi parametresi : referans ile geçti; yazma işlemleri orijinal diziyi değiştirir.
Unutmayın - PHP, ve işareti olmayan dizi parametresine yazdığınız anda değer kopyalar . Anlamı bu copy-on-write
. Size bu davranışın C kaynağını göstermek isterim, ama orada korkutucu. Daha iyi xdebug_debug_zval () kullanın .
Pascal MARTIN haklıydı. Kosta Kontos daha da öyleydi.
Cevap
Değişir.
Uzun versiyon
Sanırım bunu kendim için yazıyorum. Bir blogum falan olmalı ...
İnsanlar referanslardan (veya bu konuda işaretçilerden) bahsettiklerinde, genellikle bir logomachy ile sonuçlanırlar (sadece bu konuya bakın !).
PHP saygıdeğer bir dil olmak, (Bu yukarıdaki cevapların bir özeti olsa bile) karışıklık kadar eklemeniz gerektiğini düşündüm. Çünkü, iki kişi aynı anda haklı olsa da, kafalarını tek bir cevapta kırmak daha iyidir.
Öncelikle, siyah beyaz bir şekilde cevap vermezseniz bilgiç olmadığınızı bilmelisiniz . İşler "evet / hayır" dan daha karmaşıktır.
Gördüğünüz gibi, tüm by-value / by-reference şey, yöntem / işlev kapsamınızdaki bu diziyle tam olarak ne yaptığınızla çok ilgilidir: onu okumak veya değiştirmek mi?
PHP ne diyor? (aka "değişim-bilge")
Manuel bu (vurgu benim) diyor ki:
Varsayılan olarak, işlev bağımsız değişkenleri değere göre iletilir (böylece işlev içindeki bağımsız değişkenin değeri değiştirilirse , işlevin dışında değiştirilmez). Bir işlevin bağımsız değişkenlerini değiştirmesine izin vermek için , bunların başvuru ile iletilmesi gerekir .
Her zaman başvuru ile iletilen bir işleve bağımsız değişken edinmek için, işlev tanımındaki bağımsız değişken adına bir ve işareti (&) ekleyin
Anlayabildiğim kadarıyla, büyük, ciddi, dürüst-Tanrı programcıları referanslar hakkında konuştuğunda, genellikle bu referansın değerini değiştirmek hakkında konuşurlar . Ve bu tam olarak ne hakkında manuel görüşmeler var: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
Yine de bahsetmedikleri başka bir durum daha var: Ya bir şeyi değiştirmezsem - sadece oku?
Bir diziyi açıkça bir referansı işaretlemeyen bir yönteme geçirirseniz ve bu diziyi işlev kapsamında değiştirmezsek ne olur? Örneğin:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
Okuyun, yolcum.
PHP aslında ne yapıyor? (diğer bir deyişle "bellek bakımından")
Aynı büyük ve ciddi programcılar, daha da ciddi hale geldiklerinde, referanslarla ilgili olarak "bellek optimizasyonları" hakkında konuşuyorlar. PHP de öyle. Çünkü PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
, bu yüzden .
BÜYÜK dizileri çeşitli işlevlere ve PHP'nin kopyalarını oluşturmak için geçmek ideal olmazdı (sonuçta "by by value" bunu yapar):
<?php
// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1);
// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
echo count($arr); // let's just read the array
}
readArray($x);
Peki, eğer bu gerçekten by-pass olsaydı, 3mb + RAMimiz olurdu, çünkü o dizinin iki kopyası var , değil mi?
Yanlış. $arr
Değişkeni değiştirmediğimiz sürece , bu, bellek açısından bir referanstır . Sadece görmüyorsun. Bu yüzden PHP , dahili ve açık (ve işareti ile) olanları ayırt etmek için konuşurken , kullanıcı-toprak referanslarından bahseder&$someVar
.
Gerçekler
Yani, when an array is passed as an argument to a method or function is it passed by reference?
Üç (evet, üç) vaka ile geldim :
a) yöntem / işlev yalnızca dizi bağımsız değişkenini okur
b) yöntem / işlev dizi bağımsız değişkenini değiştirir
c) yöntem / işlev dizi bağımsız değişkeni açıkça bir başvuru ( Ve işareti)
İlk olarak, dizinin gerçekte ne kadar bellek yediğini görelim ( burada çalıştırın ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
O kadar bayt. Harika.
a) yöntem / işlev yalnızca dizi bağımsız değişkenini okur
Şimdi sadece bahsedilen diziyi argüman olarak okuyan bir fonksiyon yapalım ve okuma mantığının ne kadar bellek aldığını göreceğiz:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
count($arr); // read
$x = $arr[0]; // read (+ minor assignment)
$arr[0] - $arr[1]; // read
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);
Tahmin etmek ister misin? 80 kazanıyorum! Kendiniz görün . Bu, PHP kılavuzunun atladığı bölümdür. Eğer $arr
param aslında geçirilen değer-ile-edildi, sen benzer bir şey görmek istiyorum 1331840
bayt. Görünüşe göre $arr
bir referans gibi davranıyor, değil mi? O da ondan olan bir iç biri - bir referanslar.
b) yöntem / işlev dizi bağımsız değişkenini değiştirir
Şimdi, bu parametreye okumak yerine, bu parametreye yazalım :
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
Yine, kendiniz görün bu durumda 1331840. So olmaya oldukça yakın olduğunu, benim için, ama, dizi olduğunu aslında kopyalanıyor $arr
.
c) yöntem / işlev dizisi bağımsız değişkeni açıkça bir başvuru olarak işaretlenir (ve işareti ile)
Şimdi açık bir referans için bir yazma işleminin ne kadar bellek aldığını görelim ( burada çalıştırın ) - ve işareti fonksiyon imzasındaki notu not edin:
<?php
function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
Benim bahse girerim, 200 maks. Yani bu , bir ve işareti olmayan paramdan okumak kadar yaklaşık bellek yiyor .