TL; DR
a) metode / fungsi hanya membaca argumen array => referensi implisit (internal)
b) metode / fungsi memodifikasi argumen array => nilai
c) argumen metode / fungsi array secara eksplisit ditandai sebagai referensi (dengan ampersand) => referensi eksplisit (lahan pengguna)
Atau ini:
- param array non-ampersand : disahkan oleh referensi; operasi penulisan mengubah salinan array yang baru, salinan yang dibuat pada penulisan pertama;
- parameter array ampersand : disahkan oleh referensi; operasi penulisan mengubah array asli.
Ingat - PHP melakukan copy- nilai saat Anda menulis ke param array non-ampersand. Itu copy-on-write
artinya. Saya ingin menunjukkan sumber C perilaku ini kepada Anda, tetapi menakutkan di sana. Lebih baik gunakan xdebug_debug_zval () .
Pascal MARTIN benar. Kosta Kontos bahkan lebih.
Menjawab
Tergantung.
Versi panjang
Saya pikir saya menulis ini untuk diri saya sendiri. Saya harus punya blog atau sesuatu ...
Setiap kali orang berbicara tentang referensi (atau petunjuk, dalam hal ini), mereka biasanya berakhir dengan gegabah (lihat saja utas ini !).
PHP menjadi bahasa yang terhormat, saya pikir saya harus menambahkan hingga kebingungan (meskipun ini ringkasan jawaban di atas). Karena, walaupun dua orang bisa benar pada saat yang sama, Anda lebih baik hanya memecahkan kepala bersama menjadi satu jawaban.
Pertama-tama, Anda harus tahu bahwa Anda bukan seorang yang jago jika Anda tidak menjawab dengan cara hitam-putih . Hal-hal lebih rumit daripada "ya / tidak".
Seperti yang akan Anda lihat, keseluruhan hal berdasarkan nilai / referensi adalah sangat terkait dengan apa sebenarnya yang Anda lakukan dengan array itu dalam metode / fungsi Anda: membacanya atau memodifikasinya?
Apa kata PHP? (alias "perubahan bijaksana")
The pengguna mengatakan ini (penekanan):
Secara default, argumen fungsi dilewatkan oleh nilai (sehingga jika nilai argumen di dalam fungsi diubah , itu tidak bisa diubah di luar fungsi). Untuk memungkinkan suatu fungsi memodifikasi argumennya, mereka harus dilewatkan dengan referensi .
Agar argumen ke suatu fungsi selalu dilewatkan oleh referensi, tambahkan sebuah ampersand (&) ke nama argumen dalam definisi fungsi
Sejauh yang saya tahu, ketika programmer besar, serius, jujur kepada Tuhan berbicara tentang referensi, mereka biasanya berbicara tentang mengubah nilai referensi itu . Dan itulah yang pembicaraan pengguna tentang: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
Ada kasus lain yang tidak mereka sebutkan: bagaimana jika saya tidak mengubah apa pun - baca saja?
Bagaimana jika Anda meneruskan array ke metode yang tidak secara eksplisit menandai referensi, dan kami tidak mengubah array itu di lingkup fungsi? Misalnya:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
Baca terus, sesama pelancong.
Apa yang sebenarnya dilakukan PHP? (alias "memori-bijaksana")
Pemrogram besar dan serius yang sama, ketika mereka menjadi lebih serius, mereka berbicara tentang "optimasi memori" dalam hal referensi. Begitu juga PHP. Karena PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
itu sebabnya .
Tidaklah ideal untuk melewatkan array BESAR ke berbagai fungsi, dan PHP untuk membuat salinannya (setelah itu apa yang dilakukan "pass-by-value"):
<?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);
Nah sekarang, jika ini benar-benar nilai pass-by-value, kita akan memiliki 3MB + RAM hilang, karena ada dua salinan dari array itu, kan?
Salah. Selama kita tidak mengubah $arr
variabel, itu adalah referensi, berdasarkan ingatan . Anda hanya tidak melihatnya. Itu sebabnya PHP menyebutkan referensi pengguna-lahan ketika berbicara tentang &$someVar
, untuk membedakan antara yang internal dan eksplisit (dengan ampersand).
Fakta
Begitu, when an array is passed as an argument to a method or function is it passed by reference?
Saya datang dengan tiga (yeah, tiga) kasus:
a) metode / fungsi hanya membaca argumen array
b) metode / fungsi memodifikasi argumen array
c) argumen metode / fungsi array secara eksplisit ditandai sebagai referensi (dengan simbol untuk 'dan)
Pertama, mari kita lihat berapa banyak memori yang sebenarnya dimakan array (jalankan di sini ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
Itu banyak byte. Bagus.
a) metode / fungsi hanya membaca argumen array
Sekarang mari kita membuat fungsi yang hanya membaca array kata sebagai argumen dan kita akan melihat berapa banyak memori yang dibutuhkan oleh logika pembacaan:
<?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);
Ingin menebak? Saya mendapat 80! Lihat sendiri . Ini adalah bagian yang dihilangkan manual PHP. Jika $arr
param benar-benar di-by-value, Anda akan melihat sesuatu yang mirip dengan 1331840
byte. Tampaknya itu $arr
berlaku seperti referensi, bukan? Itu karena itu adalah referensi - yang internal.
b) metode / fungsi memodifikasi argumen array
Sekarang, mari menulis ke param itu, alih-alih membacanya:
<?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);
Sekali lagi, lihat sendiri , tapi, bagi saya, itu cukup dekat untuk menjadi 1331840. Jadi dalam hal ini, array yang sebenarnya sedang disalin ke $arr
.
c) argumen metode / fungsi array secara eksplisit ditandai sebagai referensi (dengan ampersand)
Sekarang mari kita lihat berapa banyak memori yang dibutuhkan oleh operasi tulis untuk referensi eksplisit (jalankan di sini ) - perhatikan ampersand pada tanda tangan fungsi:
<?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);
Taruhan saya adalah Anda mendapatkan 200 maks! Jadi ini memakan sekitar memori sebanyak membaca dari param non-ampersand .