PHP Belleğindeki Nesnelere ve Referanslara Giriş

Yayınlanan: 2022-03-11

Bu makaleyi ilk olarak PHP sertifikam için çalışırken, PHP'nin bellekteki değişkenleri ve nesneleri nasıl yönettiğini daha iyi anlamak için hazırladım. Çok fazla araştırmadan sonra, sorularıma cevap bulmanın kolay olmadığını fark ettim, bu yüzden bitirdikten sonra, insanların hepsini tek bir yerde bulabilmesi için bilgileri belgelemeye karar verdim.

Bu yazıda, tartışma ve farklı görüşler üretebilecek bir konu olduğu için, nesne ve değişken referanslarının bellekte nasıl kontrol edildiğinden bahsedeceğim. Üzerinde düşünülmesi gereken bir soru şudur: "Varsayılan olarak, nesneler PHP'de referansla mı yoksa kopyayla mı aktarılır?" İlk önce PHP'de hangi referansların bulunmadığından bahsedeceğim; ikinci olarak ne olduklarından bahsedeceğim ve son olarak PHP'de çöp toplayıcının nasıl çalıştığını inceleyeceğim.

$a = new Foo(); gibi bir ifade gerçekleştirirken PHP bellekte nasıl nesneler yaratır? ? Günümüzde bellek geçmişte olduğu kadar pahalı ve sınırlı bir kaynak değildir. Bununla birlikte, iyi PHP geliştiricilerinin, uygulamalarının yürütülmesi sırasında değişkenlerin ve nesnelerin dahili olarak nasıl yönetildiğini bilmesi ve anlaması yine de önemlidir.

PHP belleğindeki nesneler ve referanslar ve PHP çöp toplama

PHP'de Nesneler ve Referanslar

Pek çok kişi, PHP kitaplarında ve çevrimiçi olarak, PHP'deki nesnelerin varsayılan olarak referans olarak iletildiğini söylüyor. Diğerleri, PHP'deki nesnelerin kopya ile tahsis edildiğini söylüyor. Hangi ifadenin doğru olduğunu bulmak için önce PHP'de referansın ne olduğunu (ve ne olmadığını) analiz etmeliyiz.

PHP'de Referanslar Ne Değildir ?

PHP'de hangi referansların olduğunu bilmekten daha önemli olan ne olmadıklarını bilmektir. PHP'de referanslar C tarzı işaretçiler değildir; C pointer'larda olduğu gibi referanslarla aritmetik işlemler yapamazsınız. Niye ya? Çünkü, C'den farklı olarak, PHP referansları bir hafıza konumunu gösteren sayılar olmadığı için gerçekten hafıza adresleri değildir. Ama sonra, referanslar nelerdir ?

PHP'de Referanslar Nelerdir ?

PHP'de referanslar, iki farklı değişkenin tek bir değeri okuyup yazmasına izin veren "takma adlardır". Başka bir deyişle, farklı isimlerdeki değişkenlerden aynı değere erişime izin vererek aynı değişkenmiş gibi davranmalarını sağlayan mekanizmalardır. PHP'de değişken isimlerinin ve değişkenlerin içeriğinin tamamen farklı iki şey olduğunu ve “semboller tablosu” olarak adlandırılan şeye bağlı olduğunu unutmayın. Bu nedenle, bir referans oluşturduğumuzda, o değişken için sembol tablosuna bir takma ad ekler. Aşağıdaki kodumuz olduğunu varsayalım:

 $a = new Foo();

Yukarıdaki ifade yürütüldüğünde, bellekte $a değişkeni oluşturulur, bellekte Foo türünde bir nesne oluşturulur ve sembol tablosuna $a değişkeninin “referanslar” (veya , veya işaret eder veya ona ne ad vermek isterseniz) Foo nesnesine işaret eder, ancak bu nesnenin kendi başına bir işaretçisi değildir. Kavramsal olarak, şu çizime benzer bir şeye sahibiz:

PHP belleğindeki nesne referansları

Pop quiz: Bunu uygularsak ne olur?

 $b = $a;

$b , $a a'nın bir referansı haline gelmez; $b $a kopyası olduğunu da söyleyemeyiz. Gerçekte olan, bellekte yeni bir $b değişkeni yarattık ve sonra semboller tablosuna $b değişkeninin aynı zamanda $a a ile aynı Foo nesnesine başvurduğunu gösteren yeni bir girdi ekledik. Yani, görsel olarak, bu resimde gösterilene benzer bir şeye sahibiz:

PHP belleğindeki nesne referansları

Şimdi, çalıştırırsak:

 $c = &$a;

Bellekte üçüncü bir $c değişkeni yaratmış olacağız, ancak sembol tablosunda $c için yeni bir girdi oluşturmayacağız. Bunun yerine, semboller tablosunda, $c öğesinin $a için bir takma ad olduğu kaydedilir, bu nedenle aynı şekilde davranır, ancak $c , işaretçilere işaretçiler adı verilen bir şey oluşturan C'den farklı olarak $a için bir işaretçi değildir. Görselleştirmek için, bu resimde gösterilene benzer bir şeye sahibiz:

Değişkenlerin diyagramı ve takma adları

Bu üç değişkenden herhangi birinin değerini değiştirmek istediğimizde (yani, yeni bir değer yazarsak), PHP, $b değişkeninin içeriğini ve $a / çiftini ayırmak için bellekte yeni bir z_val yapısı oluşturmak zorunda kalacaktır. $c böylece her biri diğerinin değerini etkilemeden bağımsız olarak değiştirilebilir. Bu nedenle, önceki komut dosyasına aşağıdaki satırı eklersek:

 $b = new Bar();

Hafızada, aşağıdaki resimde gösterildiği gibi bir durumumuz olacak:

Yukarıda açıklanan durumun grafik gösterimi

Şimdi daha eksiksiz bir örnek düşünelim:

 <?php class myClass { public $var; function __construct() { $this->var = 1; } function inc() { return ++$this->var; } } $a = new myClass(); // $a "references" a Foo object $b = $a; //b also references the same Foo object as a //($a) == ($b) == <id> of Foo object, but a and b are different entries in symbols table echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); $c = &$a; //$c is an alias of $a //($a, $c) == <id> of Foo object, c is an alias of a in the symbols table echo "$c = ";var_dump($c); $a = NULL; //The entry in the symbols table which links "$a" with Foo object is removed //Since that entry was removed, $c is not related to Foo anymore //Anyway, Foo still exists in memory and it is still linked by $b echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); echo "$c = ";var_dump($c); echo "$b->var: ".$b->inc(); echo "$b->var: ".$b->inc(); $b = NULL; //The entry in the symbols table which links "$b" with the Foo object is removed //There are no more entries in the symbols table linked to Foo, //So, Foo is not referenced anymore and can be deleted by the garbage collector echo "$b = ";var_dump($b);

Yukarıdaki betiğin uygulanmasıyla üretilen çıktı:

 $a = object(myClass)#1 (1) { ["var"]=> int(1) } $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = object(myClass)#1 (1) { ["var"]=> int(1) } $a = NULL $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = NULL $b->var: 2 $b->var: 3 $b = NULL

PHP Çöp Toplama

Son olarak, 5.3 sürümünde tanıtıldığından beri PHP çöp toplamanın nasıl çalıştığını görelim. PHP belleğindeki bir nesne veya değişken, semboller tablosunda o nesneye referans olmadığında PHP çöp toplayıcı tarafından kaldırılacaktır. Yani PHP, oluşturulduğu andan itibaren bir nesnenin referans sayacını korur, böylece PHP betiğinin yürütülmesi sırasında sayaç, ona “işaret eden” değişkenlere dayalı olarak bu referans sayacını artırır ve azaltır. Referans sayısı 0'a ulaştığında (yani, o nesneye hiçbir şey referans vermiyor ve bu nedenle kullanılmıyor), PHP bu nesneyi çıkarılabilir olarak işaretler, böylece PHP çöp toplayıcının bir sonraki geçişinde bellekten silinir. , yeniden kullanım için bu alanı boşaltmak. PHP çöp toplamanın nasıl çalıştığı hakkında daha ayrıntılı bilgi istiyorsanız, bu belgeyi okuyun.

Kapanış Düşünceleri

Umarım PHP'nin bellekteki nesneleri ve değişkenleri nasıl ele aldığını ve PHP çöp toplayıcı tarafından kaldırılması gereken nesneleri nasıl "seçtiğini" biraz açıklığa kavuşturmuşumdur.

Artık PHP'nin bellekteki değişkenleri ve nesneleri dahili olarak nasıl yönettiğini anladığınıza göre, dizüstü bilgisayarınızı alın ve öğrendiklerinizi kanıtlamak için bazı kodlarla denemeye başlayın. Değişkenler ve referanslarla oynamayı deneyin. Ayrıca, bir değişkenin değerini değiştirmenin, ona başvuran başka bir değişkenin değerini nasıl etkileyebileceğini deneyin. İşte size bir soru: Aşağıdaki kod çalıştırıldıktan sonra $a ve $b değerleri ne olacak?

 $a = '1'; $b = &$a; $b = "2$b";

PHP performans özellikleri hakkında daha fazla okumakla ilgileniyorsanız, Toptaler Vilson Duka'nın bu gönderisine göz atın.