Referanslar neden PHP'de nadiren kullanılır?


26

Bazı C ++ bilgilerim var ve orada işaretçilerin sıkça kullanıldığını biliyorum, ancak PHP açık kaynak koduna bakmaya başladım ve metotlarda referans kullanarak kod görmedim.

Bunun yerine kod, başvuruyu değişkene yönteme iletmek yerine her zaman bir dönüş değeri kullanır; bu durumda bu değişkenin değerini değiştirir ve onu döndürür.

Referansları kullanmanın daha az bellek kullandığını okudum, öyleyse neden PHP'de kullanılmıyorlar?


19
Referansa göre parametrelerin kullanılması "yan-etki programlama" dır - tek bir değer döndürmek için bir fonksiyon kullanmak, kod okurken çok daha açıktır. Bununla birlikte, oldukça az sayıda PHP çekirdek işlevi referans kullanır.
halfer

3
PHP, nesneleri varsayılan olarak referans olarak iletir.

2
dizi türleri, referansa göre geçen temel PHP işlevlerinin temel bir örneğidir
Mark Baker,

2
PHP referansları işaretçiler değildir ve göründükleri yeri tam olarak beklemiyorsanız, çoğu zaman kıçınıza acı verir.
lanzz,

2
Birden fazla iade gerekiyorsa return array($foo, $bar);velist($A, $B) = foobar();
Izkata

Yanıtlar:


49

Referansların nadiren kullanıldığı iddiası yanlıştır. Başkalarının daha önce de belirttiği gibi, referans kullanan bir ton yerel fonksiyon var, kayda değer örnekler dizi sıralama fonksiyonlarını ve preg_match()/ preg_match_all(). Bu işlevlerden herhangi birini kodunuzda kullanıyorsanız, referansları da kullanıyorsunuzdur.

Devam edersek, PHP'deki referanslar işaretçi değildir . Bir C ++ geçmişinden geldiğiniz için, kargaşayı anlayabiliyorum, ancak PHP referansları tamamen farklı bir canavar . Sembol tablosuna takma adlar . C ++ referanslarından beklediğiniz performans kazançları sadece PHP referansları için geçerli değildir.

Aslında, çoğu senaryoda değere göre geçiş yapmak, referansa göre elde etmekten daha hızlı ve daha az bellek gerektirir. PHP'nin çekirdeği olan Zend Engine, değiştirilinceye kadar bir değişkenin kopyasını oluşturmayan bir yazma-yazma optimizasyon mekanizması kullanır . Referansa göre geçmek, genellikle yazma üzerine kopyalama düzenini keser ve değeri değiştirip değiştirmemeniz için bir kopya gerektirir.

İhtiyacınız olduğunda PHP'deki referansları kullanmaktan korkmayın, ancak yalnızca mikro-optimizasyon girişiminde bulunmayın. Unutmayın, erken optimizasyon tüm kötülüklerin köküdür .

Daha fazla okuma:


@NikiC düzeltmesi için teşekkürler. Tembel bir bit cevap bu ...
yannis

Cevabı tamamlamak için tüm nesnelerin PHP'de referans olarak alındığına dikkat çekmek güzel olurdu.
Florian Margaine

@FlorianMargaine Bu tamamen doğru değil (daha fazla okuma için ikinci bağlantıya bakın).
yannis

2
@FlorianMargaine Hayır, ikisi çok farklı ve neden böyle olduğunu anlamak önemlidir.
phant0m

3
@FlorianMargaine Hayır, varsayalım nesneler edildi PHP referans olarak gönderilir: f($obj)Verilen function f($x) { $x = new X; }, olurdu $objbir atıfta farklı çağrısı önce daha nesne f(). Nesneleri Ancak, olmayan başvuruyla geçirildi PHP ile bu yürütmek olsaydı, $ nesne değiştirilmez. Bu şekilde, PHP Java ile aynı şeyi yapar.
phant0m

8

PHP zaten bir şeyi değiştirene kadar yeni bir değer yaratmadığı, üzerine yazmayı kopyalayan bir şey yapar, bu nedenle referansları kullanarak çok fazla bellek kalmaz. Bunu yapmak, PHP'nin dahili olarak yaptığı, bellek kullanımını azaltmak ve işleri daha da kötüleştirmek için dahili olarak yaptığı bazı şeylerle karışabilir.

Buna, referansların genel olarak işleri biraz fazla büyülü kıldığı gerçeğini de ekleyin. Varsayılan ve dolayısıyla çoğu insanın beklediği şey, parola değeridir; Öldüğüm zaman $ibir işleve, o işlev gizemli değiştirir umrumda zorunda müthiş şeyler zorlaştırmaktadır $itamamen başka bir şeye ve böylece her ihtimale karşı savunma kopyalarını alın. ( $iDeğerin bir nesne olup olmadığını zaten değiştirebilir , ancak bence yapmamalıydı.)

Temel olarak, ben sadece anlam ı bekliyoruz değişkenleri geçmek referans-ile- "dışarı" parametreleri için kullanışlı bulacağını geri almak işlevi yerine de pas, a la gelen preg_match'ın &$matches. İçeri giren nesneyi açıkça değiştiren işlevler için bile , sortya da gibi array_pop, kendilerini biraz sinirli hissettiriyor ... ama buna bağlı kaldık.


5

PHP web odaklı bir dildir.
Web sayfalarının hızlı sunulması ve hafif olması gerekir.
Her zamanki PHP programı saniyenin bir kısmını yaşar ve birkaç yüz kilobayt bellek tüketir.
Bu tür optimizasyonların faydası yoktur.


1
Bu. İşaretçilere / referanslara ihtiyaç duymaz, çünkü C ++ gibi düşük bir seviyede karışıklık yaratmaz.
Kenneth Worden,

8
Neden bu yayın 5+ alıyor ??? A) soruyu cevaplamamak b) doğru değil

1
Yani referanslar yavaş ve çok fazla bellek tüketiyor?
Roket Hazmat

1
@RocketHazmat Evet, garip bir şekilde bu doğru.
yannis

3

Anında bazı nedenler:

  • PHP bir betik dilidir ve çekirdek gömülü bir yazılım olarak kullanılmayı amaçlamaz (temel olarak, betiğin sonunda bellek temizlenir),
  • PHP5'ten beri, referans referansı nesne parametreleri için örtüktür (bu nedenle PHP referans satırında "arkanızda" kullanılır).

1
İkinci nokta için bakınız: php.net/manual/en/language.oop5.references.php .
yannis

2

Bence bu sadece geliştiricilerin bir seçimi, dille ilgisi yok. Çok sayıda PHP kodu (yerleşik ve değil) referansları kullanır. PHP'deki dizi işlevlerine bakın, çoğu başvuru referansı kullanın. preg_matchreferansları kullanır.

Geliştiricilerin referansları kullanmamayı seçmelerinin nedenlerinden birinin kafa karıştırıcı olabileceğinden düşünüyorum. Bir işlev çağırıyorsunuz ve değişkenlerden biri (ya da olmayabilir) bir referans olduğundan güncellenebilir. Bu nedenle, hata ayıklama yaptığınızda, $xjsut'un değerinin neden sihirli bir şekilde değiştiği açık olmayabilir .


1

Sorunuzla ilgili temel sorun, bunun C ++ 'da da yaygın olduğunu varsaymanızdır. Değil. Çıktı parametrelerini sevmiyoruz ve mümkün olduğu kadar az kullanıyoruz - bunlar yalnızca C tarzı API'lerde yaygındır.


0

Bunu yapan birçok php fonksiyonunu biliyorum . preg_match()Mesela bir göz atın . $matchesreferans ile geçilecek

Eğer kendiniz için referans alarak bağımsız değişkenleri alan bir fonksiyon yazmak istiyorsanız, aşağıdaki sözdizimini kullanın.

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ a ve $ b referansa göre verilir $ c değerine göre iletilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.