Mengapa referensi jarang digunakan dalam PHP?

26

Saya punya beberapa pengetahuan C ++ dan tahu bahwa pointer biasanya digunakan di sana, tapi saya sudah mulai melihat kode open source PHP dan saya tidak pernah melihat kode menggunakan referensi dalam metode.

Sebaliknya, kode selalu menggunakan nilai balik alih-alih meneruskan referensi ke variabel ke metode, yang kemudian mengubah nilai variabel dan hanya mengembalikannya.

Saya telah membaca bahwa menggunakan referensi menggunakan lebih sedikit memori, jadi mengapa mereka tidak digunakan dalam PHP?

Alexander Cogneau
sumber
19
Menggunakan parameter pass-by-reference adalah "pemrograman efek samping" - menggunakan fungsi untuk mengembalikan nilai tunggal secara signifikan lebih jelas ketika membaca kode. Yang mengatakan, beberapa fungsi inti PHP menggunakan referensi.
halfer
3
PHP melewati objek dengan referensi secara default.
2
macam array adalah contoh utama dari fungsi PHP inti yang lulus dengan referensi
Mark Baker
2
Referensi PHP bukan petunjuk, dan seringkali menyebalkan jika Anda tidak mengharapkannya di mana mereka muncul.
lanzz
2
Jika Anda perlu beberapa pengembalian, return array($foo, $bar);danlist($A, $B) = foobar();
Izkata

Jawaban:

49

Penegasan Anda bahwa referensi jarang digunakan tidak benar. Seperti yang orang lain telah sebutkan ada banyak fungsi asli yang menggunakan referensi, contoh penting termasuk fungsi penyortiran array dan preg_match()/ preg_match_all(). Jika Anda menggunakan salah satu fungsi ini dalam kode Anda, Anda juga menggunakan referensi.

Selanjutnya, referensi dalam PHP bukan petunjuk. Karena Anda berasal dari latar belakang C ++ saya bisa mengerti kebingungan, tetapi referensi PHP adalah binatang yang sama sekali berbeda, mereka alias ke tabel simbol . Setiap peningkatan kinerja yang Anda harapkan dari referensi C ++ tidak berlaku untuk referensi PHP.

Bahkan, dalam sebagian besar skenario, lewat nilai lebih cepat dan kurang intensif memori daripada lewat referensi. Zend Engine, inti PHP, menggunakan mekanisme optimisasi copy-on-write yang tidak membuat salinan variabel hingga dimodifikasi. Melewati dengan referensi biasanya mematahkan pola copy-on-write dan memerlukan salinan apakah Anda mengubah nilai atau tidak.

Jangan takut untuk menggunakan referensi dalam PHP ketika Anda perlu, tetapi jangan hanya melakukannya sebagai upaya untuk mengoptimalkan mikro. Ingat, optimasi prematur adalah akar dari semua kejahatan .

Bacaan lebih lanjut:

yannis
sumber
Terima kasih atas koreksi @NikiC. Sedikit yang malas jawab yang ini ...
yannis
Untuk melengkapi jawabannya, alangkah baiknya untuk menunjukkan bahwa semua objek dilewatkan dengan referensi dalam PHP.
Florian Margaine
@FlorianMargaine Itu tidak sepenuhnya akurat (lihat tautan kedua dalam bacaan lebih lanjut).
yannis
2
@FlorianMargaine Tidak, keduanya sangat berbeda dan penting untuk menyadari mengapa demikian.
phant0m
3
@FlorianMargaine ada, benda misalkan yang disahkan oleh acuan dalam PHP: f($obj)diberikan function f($x) { $x = new X; }, harus $objmengacu pada yang berbeda objek dari sebelumnya panggilan untuk f(). Namun, karena objek tidak lulus dengan referensi, $ obj tidak dimodifikasi jika Anda menjalankan ini dengan PHP. Dengan cara itu, PHP melakukan hal yang sama dengan Java.
phant0m
8

PHP sudah melakukan copy-on-write di mana hal itu tidak menciptakan nilai baru sampai Anda mengubah sesuatu, jadi tidak ada banyak memori yang disimpan dengan menggunakan referensi. Melakukannya bahkan dapat mengacaukan beberapa hal yang dilakukan PHP secara internal untuk mengurangi penggunaan memori, membuat segalanya menjadi lebih buruk.

Tambahkan ke fakta bahwa referensi membuat hal-hal agak terlalu ajaib secara umum. Default, dan dengan demikian apa yang kebanyakan orang harapkan, adalah nilai per nilai; ketika saya beralih $ike suatu fungsi, hal itu sangat rumit untuk harus peduli apakah fungsi itu secara misterius berubah $imenjadi sesuatu yang lain, dan dengan demikian membuat salinan defensif untuk berjaga-jaga. (Ini sudah dapat memodifikasi $ijika nilainya adalah objek, tetapi menurut saya tidak seharusnya.)

Pada dasarnya, saya hanya akan menemukan pass-by-referensi yang berguna untuk "keluar" parameter, yang berarti variabel saya berharap untuk mendapatkan kembali dari fungsi daripada lulus dalam, ala preg_match's &$matches. Bahkan untuk fungsi yang secara jelas memodifikasi objek yang dilewatkan, seperti sortatau array_pop, yang terasa agak menjengkelkan ... tapi itulah yang kita terjebak.

cao
sumber
5

PHP adalah bahasa yang berorientasi web.
Halaman web dilayani dengan cepat dan harus ringan.
Program PHP biasa tinggal sebagian kecil dan mengkonsumsi beberapa ratus kilobyte memori.
Tidak ada gunanya untuk optimasi seperti itu.

Akal Sehat Anda
sumber
1
Ini. Tidak perlu pointer / referensi, karena tidak mengacaukan pada level rendah seperti C ++.
Kenneth Worden
8
Mengapa postingan ini mendapat 5+ ??? Itu a) tidak menjawab pertanyaan b) tidak benar
1
Jadi referensi lambat dan terlalu banyak menggunakan memori?
Rocket Hazmat
1
@ RockHazmat Ya, anehnya itu benar.
yannis
3

Beberapa alasan dengan cepat:

  • PHP adalah bahasa scripting, dan tidak bertujuan untuk digunakan sebagai perangkat lunak inti yang tertanam (pada dasarnya, memori dihapus pada akhir skrip),
  • Sejak PHP5, pass-by-reference adalah implisit untuk parameter objek (jadi PHP menggunakan pass-by-reference "di belakang Anda").
AlterPHP
sumber
1
Lihat: php.net/manual/en/language.oop5.references.php untuk poin kedua Anda.
yannis
2

Saya pikir ini hanya pilihan pengembang, tidak ada hubungannya dengan bahasa. Banyak kode PHP (bawaan dan bukan) menggunakan referensi. Lihatlah fungsi-fungsi array dalam PHP, banyak yang menggunakan referensi. preg_matchmenggunakan referensi.

Saya pikir salah satu alasan pengembang memilih untuk tidak menggunakan referensi adalah karena dapat membingungkan. Anda memanggil suatu fungsi dan salah satu variabel mungkin (atau mungkin tidak) diperbarui karena itu adalah referensi. Jadi, ketika Anda debug, mungkin tidak jelas mengapa nilai $xjsut berubah secara ajaib.

Roket Hazmat
sumber
1

Masalah mendasar dengan pertanyaan Anda adalah Anda menganggap bahwa ini juga umum di C ++. Bukan itu. Kami tidak suka parameter output dan menggunakannya sesedikit mungkin - mereka hanya benar-benar umum di C-style API

DeadMG
sumber
0

Saya tahu banyak fungsi php yang melakukannya. Lihat preg_match()misalnya.$matchesakan diteruskan dengan referensi

Jika Anda ingin menulis fungsi untuk diri sendiri yang menggunakan argumen dengan referensi, gunakan sintaks berikut

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

$ a dan $ b disahkan oleh referensi $ c dilewatkan oleh nilai.

hek2mgl
sumber