Pengenalan Objek dan Referensi dalam Memori PHP
Diterbitkan: 2022-03-11Saya pertama kali menyusun artikel ini saat belajar untuk sertifikasi PHP saya dalam upaya untuk lebih memahami bagaimana PHP mengelola variabel dan objek dalam memori. Setelah banyak penelitian, saya menyadari bahwa tidak mudah untuk menemukan jawaban atas pertanyaan saya, jadi setelah saya selesai, saya memutuskan untuk mendokumentasikan informasi sehingga orang dapat menemukan semuanya di satu tempat.
Dalam artikel ini, saya akan berbicara tentang bagaimana referensi objek dan variabel dikendalikan dalam memori, karena ini adalah masalah yang dapat menimbulkan diskusi dan perbedaan pendapat. Satu pertanyaan untuk direnungkan adalah: “Secara default, apakah objek dilewatkan dengan referensi atau dengan salinan di PHP?” Saya akan berbicara dulu tentang referensi apa yang tidak ada di PHP; kedua, saya akan membahas apa itu , dan terakhir, saya akan memeriksa cara kerja pengumpul sampah di PHP.
Bagaimana PHP membuat objek di memori saat melakukan pernyataan seperti $a = new Foo();
? Saat ini, memori tidak semahal dan sumber daya yang terbatas seperti di masa lalu. Namun, tetap penting bagi pengembang PHP yang baik untuk mengetahui dan memahami bagaimana variabel dan objek dikelola secara internal selama eksekusi aplikasi mereka.
Objek dan Referensi di PHP
Banyak orang mengatakan—dalam buku PHP dan online—bahwa objek dalam PHP diteruskan dengan referensi secara default. Yang lain mengatakan bahwa objek dalam PHP dialokasikan oleh salinan. Untuk mengetahui pernyataan mana yang benar, pertama-tama kita harus menganalisis apa yang (dan apa yang tidak) referensi dalam PHP.
Apa yang Bukan Referensi di PHP?
Lebih penting daripada mengetahui referensi apa yang ada di PHP adalah mengetahui apa yang bukan referensi. Di PHP, referensi bukan pointer gaya-C; Anda tidak dapat melakukan operasi aritmatika dengan referensi seperti yang Anda bisa dengan pointer C. Mengapa? Karena, tidak seperti di C, referensi PHP sebenarnya bukan alamat memori, karena bukan angka yang menunjukkan lokasi memori. Tapi kemudian, apa itu referensi?
Apa Itu Referensi di PHP?
Di PHP, referensi adalah "alias" yang memungkinkan dua variabel berbeda untuk membaca dan menulis satu nilai. Dengan kata lain, mereka adalah mekanisme yang memungkinkan akses ke nilai yang sama dari variabel dengan nama yang berbeda sehingga mereka berperilaku seolah-olah mereka adalah variabel yang sama. Perlu diingat bahwa di PHP, nama variabel dan konten variabel adalah dua hal yang sama sekali berbeda, dihubungkan dalam apa yang disebut "tabel simbol." Jadi, ketika kita membuat referensi, itu hanya menambahkan alias untuk variabel itu di tabel simbol. Misalkan kita memiliki kode berikut:
$a = new Foo();
Ketika pernyataan di atas dijalankan, variabel $a
dibuat di memori, objek bertipe Foo
dibuat di memori, dan entri ditambahkan ke tabel simbol yang menunjukkan bahwa variabel $a
"referensi" (atau terkait dengan , atau menunjuk ke, atau apa pun yang Anda ingin menyebutnya) objek Foo
, tetapi itu bukan penunjuk ke objek itu, per se. Secara konseptual, kami memiliki sesuatu seperti ilustrasi ini:
Kuis pop: Apa yang terjadi jika kita menjalankan ini?
$b = $a;
Bukannya $b
menjadi referensi dari $a
; kita juga tidak dapat mengatakan bahwa $b
adalah salinan dari $a
. Apa yang sebenarnya terjadi adalah kita telah membuat variabel baru $b
di memori dan kemudian menambahkan entri baru di tabel simbol yang menunjukkan bahwa variabel $b
juga mereferensikan objek Foo
yang sama dengan yang dilakukan $a
. Jadi, secara visual, kami memiliki sesuatu yang mirip dengan apa yang ditunjukkan dalam ilustrasi ini:
Sekarang, jika kita mengeksekusi:
$c = &$a;
Kami akan membuat variabel ketiga $c
di memori, tetapi bukan entri baru di tabel simbol untuk $c
. Sebagai gantinya, dalam tabel simbol, dicatat bahwa $c
adalah alias untuk $a
, sehingga akan berperilaku identik, tetapi $c
bukan pointer ke $a
—tidak seperti di C, yang menciptakan sesuatu yang disebut pointers to pointers . Untuk memvisualisasikan, kami memiliki sesuatu yang mirip dengan apa yang ditunjukkan dalam ilustrasi ini:

Segera setelah kita ingin mengubah nilai salah satu dari ketiga variabel ini (yaitu, menulis nilai baru), PHP harus membuat struktur z_val
baru di memori untuk memisahkan konten variabel $b
dan pasangan $a
/ $c
sehingga masing-masing dapat dimodifikasi secara independen tanpa mempengaruhi nilai yang lain. Jadi, jika kita menambahkan baris berikut ke skrip sebelumnya:
$b = new Bar();
Dalam memori, kita akan memiliki situasi seperti yang diwakili dalam ilustrasi berikut:
Sekarang, mari kita pertimbangkan contoh yang lebih lengkap:
<?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);
Output yang dihasilkan dari implementasi script di atas adalah:
$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
Pengumpulan Sampah PHP
Terakhir, mari kita lihat cara kerja pengumpulan sampah PHP, sejak diperkenalkan di versi 5.3. Objek atau variabel dalam memori PHP akan dihapus oleh pengumpul sampah PHP ketika tidak ada referensi ke objek tersebut di tabel simbol. Artinya, PHP memelihara penghitung referensi suatu objek sejak dibuat sehingga selama eksekusi skrip PHP, penghitung menambah dan mengurangi penghitung referensi berdasarkan variabel yang "menunjuk" ke sana. Setelah jumlah referensi mencapai 0 (yaitu, tidak ada yang mereferensikan objek tersebut dan, oleh karena itu, objek tersebut tidak digunakan), PHP menandai objek tersebut sebagai dapat dilepas, sehingga pada langkah berikutnya dari pengumpul sampah PHP, objek tersebut akan dihapus dari memori , membebaskan ruang tersebut untuk digunakan kembali. Jika Anda ingin detail lebih mendalam tentang cara kerja pengumpulan sampah PHP, baca dokumentasi ini.
Pikiran Penutup
Saya harap saya telah mengklarifikasi sedikit bagaimana PHP menangani objek dan variabel dalam memori dan bagaimana "memilih" objek yang harus dihapus oleh pengumpul sampah PHP.
Sekarang setelah Anda memahami bagaimana PHP mengelola variabel dan objek dalam memori secara internal, ambil laptop Anda dan mulailah bereksperimen dengan beberapa kode untuk membuktikan apa yang telah Anda pelajari. Cobalah bermain-main dengan variabel dan referensi. Juga, bereksperimenlah dengan bagaimana mengubah nilai variabel dapat memengaruhi nilai referensi lain. Berikut pertanyaan untuk Anda: Berapa nilai $a
dan $b
setelah kode di bawah ini dijalankan?
$a = '1'; $b = &$a; $b = "2$b";
Jika Anda tertarik untuk membaca lebih lanjut tentang fitur kinerja PHP, lihat posting ini oleh sesama Toptaler Vilson Duka.