Pengguna anonim
Lebih
Apa's perbedaan antara lewat referensi vs. lewat nilai?
Apa perbedaan antara
- parameter yang dikirimkan dengan referensi
- parameter lulus dengan nilai?
Bisa anda berikan beberapa contoh, please?
538
15
Pertama dan terpenting, "lulus dengan nilai vs. lewat referensi" perbedaan seperti yang didefinisikan dalam teori CS ini sekarang usang karena teknik awalnya didefinisikan sebagai "lewat referensi" sejak jatuh dari nikmat dan ini jarang digunakan sekarang.1 Baru bahasa2 cenderung menggunakan yang berbeda (tapi mirip) sepasang teknik untuk mencapai efek yang sama (lihat di bawah) yang merupakan sumber utama dari kebingungan. Sumber sekunder kebingungan adalah kenyataan bahwa di "lewat referensi", "referensi" memiliki lebih sempit makna dari istilah umum "referensi" (karena kalimat mendahului itu).
Sekarang, otentik definisi adalah:
Arti dari "referensi" dalam "lewat referensi". Perbedaan umum "referensi" istilah ini adalah bahwa "referensi" adalah sementara dan implisit. Apa yang callee pada dasarnya akan lebih "variabel" yang entah bagaimana "yang" sebagai yang asli. Cara khusus efek ini dicapai adalah tidak relevan (misalnya bahasa juga dapat mengekspos beberapa rincian pelaksanaan -- alamat, pointer, dereferencing -- ini adalah semua yang tidak relevan; jika efek bersih adalah ini, itu's pass-by-reference).
Sekarang, dalam bahasa modern, variabel cenderung "jenis referensi" (konsep lain yang diciptakan lebih dari "lewat referensi" dan terinspirasi oleh itu), yaitu objek yang sebenarnya data disimpan secara terpisah di suatu tempat (biasanya, pada tumpukan), dan hanya "referensi" untuk itu yang pernah diadakan di variabel dan lulus sebagai parameter.3 Lewat referensi tersebut berada di bawah pass-by-value karena variabel's nilai teknis referensi itu sendiri, bukan disebut objek. Namun, efek bersih pada program bisa sama baik sebagai pass-by-value atau pass-by-reference:
Fungsional bahasa, all benda-benda yang tidak berubah. Seperti yang anda lihat, sepasang teknik ini hampir sama dengan definisi, hanya dengan tingkat tipuan: hanya mengganti "variabel" dengan "objek direferensikan". Ada's tidak disepakati nama untuk mereka, yang mengarah ke berkerut penjelasan seperti "panggilan dengan nilai yang mana nilai referensi". Pada tahun 1975, Barbara Liskov menyarankan istilah "call-by-objek-berbagi" (atau kadang-kadang hanya "call-by-sharing") meskipun itu tidak pernah tertangkap. Selain itu, tidak satu pun dari frase ini menarik paralel dengan pasangan aslinya. Tidak heran istilah lama akhirnya menjadi kembali dalam ketiadaan dari sesuatu yang lebih baik, yang menyebabkan kebingungan.4
CATATAN: Untuk waktu yang lama, jawaban ini digunakan untuk mengatakan:
It's cara bagaimana untuk melewati argumen untuk fungsi. Passing by reference berarti disebut fungsi' parameter akan sama seperti penelepon' argumen berlalu (bukan nilai, tapi identitas - variabel itu sendiri). Lulus dengan nilai yang berarti disebut fungsi' parameter akan menjadi copy dari penelepon' argumen berlalu. Nilai akan sama, tetapi identitas - variabel - berbeda. Dengan demikian perubahan parameter dilakukan oleh yang disebut fungsi dalam satu kasus perubahan argumen yang dilewatkan dan dalam kasus lain hanya perubahan nilai parameter di atas disebut fungsi (yang hanya copy). Dalam cepat cepat:
ref
digunakan pada pemanggil dan disebut fungsi). Jon Skeet juga memiliki penjelasan ini di sini.Kode
Sejak saya bahasa C++, saya akan menggunakannya di sini
Dan contoh di Jawa won't sakit:
Wikipedia
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
Orang ini cukup banyak kuku ini:
http://javadude.com/articles/passbyvalue.htm
Banyak jawaban di sini (dan khususnya yang paling sangat upvoted jawaban) yang secara faktual tidak benar, karena mereka salah memahami apa "panggilan dengan referensi" benar-benar berarti. Berikut ini's my upaya untuk mengatur hal-hal lurus.
TL;DR
Dalam istilah sederhana:
Apa "call by value" dan "panggilan dengan referensi" don't berarti
Perhatikan bahwa kedua konsep ini benar-benar independen dan ortogonal dari konsep jenis referensi (yang di Jawa adalah semua jenis yang subtipe
Objek
, dan di C# semuakelas
jenis), atau konsep pointer jenis seperti di C (yang secara semantis setara dengan Java's "jenis referensi", cukup dengan sintaks yang berbeda). Gagasan tipe referensi sesuai dengan URL: lebih baik sendiri merupakan bagian dari informasi, dan itu adalah referensi (a pointer, jika anda mau) untuk informasi lainnya. Anda dapat memiliki banyak salinan URL di tempat yang berbeda, dan mereka don't perubahan apa website mereka semua link ke; jika website ini diperbarui maka setiap URL copy masih akan menyebabkan informasi terbaru. Sebaliknya, mengubah URL di satu tempat tidak't mempengaruhi yang lain salinan tertulis dari URL. Perhatikan bahwa C++ memiliki gagasan "referensi" (misalnyaint&
) yang tidak ** seperti Java dan C#'s "jenis referensi", tapi adalah* seperti "panggilan dengan referensi". Java dan C#'s "jenis referensi", dan semua jenis Python, seperti apa C dan C++ panggilan "pointer jenis" (misalnya `int`).OK, di sini's lebih lama dan lebih formal penjelasan.
Terminologi
Untuk mulai dengan, saya ingin menyoroti beberapa bit penting dari terminologi, untuk membantu memperjelas jawaban saya dan untuk memastikan kami're semua mengacu pada ide-ide yang sama ketika kita menggunakan kata-kata. (Dalam prakteknya, saya percaya sebagian besar dari kebingungan tentang topik-topik seperti ini berasal dari menggunakan kata-kata dalam cara-cara yang tidak sepenuhnya berkomunikasi dengan makna yang dimaksudkan.) Untuk memulai, berikut ini's contoh dalam beberapa bahasa C-seperti dari deklarasi fungsi:
Dan berikut's contoh pemanggilan fungsi ini:
Menggunakan contoh ini, saya ingin menjelaskan beberapa bit penting dari terminologi:
foo
adalah fungsi menyatakan pada baris 1 (Jawa bersikeras untuk melakukan semua fungsi metode, tapi konsep yang sama tanpa kehilangan umum; C dan C++ membuat perbedaan antara deklarasi dan definisi yang saya tidak't pergi ke sini)param
adalah parameter formal untukfoo
, juga dinyatakan pada baris 1arg
adalah variabel, khusus variabel lokal fungsibar
, dideklarasikan dan diinisialisasi pada baris 2arg
juga argumen tertentu doa darifoo
on line 3 Ada dua hal yang sangat penting set konsep untuk membedakan di sini. Yang pertama adalah nilai terhadap variabel:bar
fungsi di atas, setelah barisint arg = 1;
, ungkapanarg
memiliki nilai1
.final
atau C#'sreadonly
) atau sangat berubah (misalnya dengan menggunakan C++'sconst
). Hal penting lain yang sepasang-konsep yang membedakan adalah parameter terhadap argumen:Call by value
Di call by value, fungsi's parameter formal adalah variabel yang baru dibuat untuk fungsi doa, dan yang diinisialisasi dengan nilai ** argumen mereka. Ini bekerja sama persis dengan cara yang sama bahwa setiap jenis lain dari variabel-variabel yang diinisialisasi dengan nilai-nilai. Misalnya:
Di sini
arg
dananother_variable
benar-benar independen variabel -- nilai-nilai mereka dapat mengubah secara independen dari satu sama lain. Namun, pada titik di manaanother_variable
ini menyatakan, hal ini diinisialisasi untuk memegang nilai yang sama bahwaarg
memegang-yang adalah1
. Karena mereka adalah variabel independen, perubahananother_variable
tidak mempengaruhiarg
:Ini adalah persis sama seperti hubungan antara
arg
danparam
dalam contoh kita di atas, yang saya'll ulangi di sini untuk simetri:Hal ini persis seperti jika kita menulis kode seperti ini:
Artinya, yang menentukan karakteristik apa call by value berarti bahwa callee (
foo
dalam kasus ini) menerima nilai sebagai argumen, tapi terpisah sendiri variabel untuk nilai-nilai dari variabel-variabel pemanggil (bar
dalam kasus ini). Akan kembali ke saya metafora di atas, jika saya'mbar
dan'refoo
, ketika saya menelepon anda, saya menyerahkan selembar kertas dengan nilai yang tertulis di atasnya. Kau sebut itu selembar kertasparam
. Nilai tersebut adalah copy* nilai saya telah menulis di notebook saya (saya variabel lokal), dalam sebuah variabel yang saya sebutarg
. (Sebagai samping: tergantung pada perangkat keras dan sistem operasi, ada berbagai konvensi pemanggilan* tentang bagaimana anda memanggil salah satu fungsi dari yang lain. Konvensi panggilan seperti kita memutuskan apakah saya menulis nilai pada selembar kertas saya dan kemudian menyerahkannya kepada anda, atau jika anda memiliki selembar kertas yang saya tulis ini, atau jika saya menulis di dinding di depan kami berdua. Ini adalah suatu hal yang menarik juga, tapi jauh di luar lingkup ini sudah lama menjawab.)Call by reference
Di call by reference, fungsi's parameter formal yang cukup nama-nama baru untuk variabel yang sama bahwa penelepon persediaan sebagai argumen. Kembali ke contoh kita di atas,'s setara dengan:
Sejak
param
adalah nama lain untukarg
- yaitu, mereka variabel yang sama, perubahanparam
yang tercermin dalamarg
. Ini adalah cara mendasar di mana panggilan dengan referensi yang berbeda dari call by value. Beberapa bahasa yang mendukung panggilan dengan referensi, tapi C++ dapat melakukannya seperti ini:Dalam hal ini,
param
doesn't hanya memiliki yang sama nilai sebagaiarg
, itu benar-benar adalaharg
(hanya dengan nama yang berbeda) danbar
dapat mengamati bahwaarg
telah bertambah. Catatan bahwa ini adalah tidak bagaimana setiap dari Java, JavaScript, C, Objective-C, Python, atau hampir semua bahasa populer lainnya saat ini bekerja. Ini berarti bahwa bahasa-bahasa yang tidak **** panggilan dengan referensi, yang mereka sebut dengan nilai.Tambahan: call dengan objek berbagi
Jika apa yang anda miliki adalah call by value, tapi nilai sebenarnya adalah tipe referensi atau tipe pointer, maka "nilai" sendiri isn't sangat menarik (misalnya di C's hanya sebuah integer dari platform-ukuran tertentu) -- apa yang's menarik adalah apa yang nilai poin ke. Jika apa yang tipe referensi (yaitu, pointer) poin ke bisa berubah maka efek yang menarik adalah kemungkinan: anda dapat memodifikasi menunjuk-nilai, dan penelepon dapat mengamati perubahan menunjuk-nilai, meskipun pemanggil tidak dapat mengamati perubahan pointer itu sendiri. Meminjam analogi dari URL lagi, fakta bahwa saya memberi anda copy URL ke situs web ini tidak terlalu menarik jika hal yang kita pedulikan adalah website, bukan URL. Fakta bahwa anda menulis di atas anda copy URL doesn't mempengaruhi saya copy URL isn't hal yang kita peduli tentang (dan pada kenyataannya, dalam bahasa seperti Java dan Python "URL", atau referensi jenis nilai, dapat't dapat diubah sama sekali, hanya satu hal yang ditunjukkan oleh bisa). Barbara Liskov, ketika dia menemukan CLU bahasa pemrograman (yang ini semantik), menyadari bahwa ada syarat "call by value" dan "panggilan dengan referensi" bukan't sangat berguna untuk menggambarkan semantik bahasa baru ini. Jadi dia menciptakan istilah baru: panggil oleh objek berbagi. Ketika membahas bahasa-bahasa yang secara teknis call by value, tetapi di mana jenis umum di gunakan adalah referensi atau penunjuk jenis (artinya: hampir setiap modern imperative, object-oriented, atau multi-paradigma bahasa pemrograman), saya menemukan itu's jauh lebih sedikit membingungkan untuk hanya menghindari berbicara tentang call by value atau call by reference. Menempel panggil oleh objek berbagi (atau hanya panggil oleh obyek) dan tak seorang pun akan menjadi bingung. :-)
Sebelum memahami 2 hal, anda *HARUS *** memahami berikut. Setiap objek memiliki 2 hal-hal yang dapat membuatnya dapat dibedakan.
Jadi jika anda mengatakan
karyawan.nama = "John"
tahu bahwa ada 2 hal tentang
nama
. Nilai yang lebih"John"
dan juga lokasi di memori yang beberapa nomor heksadesimal, mungkin seperti ini:0x7fd5d258dd00
.Tergantung pada bahasa yang's arsitektur atau jenis (kelas, struct, dll.) dari objek anda, anda akan baik mentransfer
"John"
atau0x7fd5d258dd00
Lewat
"John"
dikenal sebagai passing by value. Lewat0x7fd5d258dd00
dikenal sebagai lewat referensi. Siapa saja yang menunjuk ke lokasi memori akan memiliki akses ke nilai"John"
.Untuk lebih lanjut tentang ini, saya sarankan anda untuk membaca tentang dereferensi pointer dan juga mengapa memilih struct (value type) atas kelas (tipe referensi)
Berikut ini sebuah contoh:
Cara paling sederhana untuk mendapatkan ini pada file Excel. Katakanlah misalnya bahwa anda memiliki dua nomor, 5 dan 2 di sel A1 dan B1 yang sesuai, dan anda ingin menemukan jumlah mereka di sel ketiga, let's mengatakan A2. Anda dapat melakukan ini dalam dua cara.
Baik dengan melewati nilai-nilai mereka ke sel A2 dengan mengetik = 5 + 2 ke dalam sel ini. Dalam hal ini, jika nilai sel A1 atau B1 perubahan, jumlah A2 tetap sama.
Atau dengan lewat "referensi" dari sel A1 dan B1 ke sel A2 dengan mengetik = A1 + B1. Dalam hal ini, jika nilai sel A1 atau B1 perubahan, jumlah A2 perubahan juga.
Ketika lewat ref anda pada dasarnya melewati pointer ke variabel. Lulus dengan nilai yang anda menyampaikan salinan dari variabel. Dalam penggunaan dasar ini biasanya berarti lewat ref perubahan variabel akan terlihat menjadi yang memanggil metode dan lulus dengan nilai yang mereka tidak.
Lulus dengan nilai mengirimkan SALINAN data yang disimpan dalam variabel yang anda tentukan, lewat referensi mengirim link langsung ke variabel itu sendiri. Jadi jika anda melewati sebuah variabel dengan referensi dan kemudian mengubah variabel dalam blok anda lulus ke, variabel asli akan berubah. Jika anda hanya lulus dengan nilai, variabel asli tidak akan dapat diubah dengan blok anda lulus menjadi tapi anda akan mendapatkan salinan apa pun yang terkandung di waktu panggilan.
Lulus dengan nilai fungsi salinan variabel dan bekerja dengan salinan(jadi itu doesn't mengubah apa pun dalam variabel asli)
Pass by reference - fungsi menggunakan variabel asli, jika anda mengubah variabel dalam fungsi lain, perubahan dalam variabel asli juga.
Contoh(copy dan menggunakan/mencoba ini untuk diri sendiri dan melihat) :
Perbedaan utama antara mereka adalah bahwa nilai-tipe variabel yang menyimpan nilai-nilai, sehingga menentukan nilai-jenis variabel dalam metode panggilan melewati copy dari variabel's nilai metode. Referensi-jenis variabel yang menyimpan referensi ke objek, sehingga menentukan referensi-jenis variabel sebagai argumen melewati metode salinan aktual referensi yang mengacu pada objek. Bahkan meskipun referensi itu sendiri adalah lulus dengan nilai, metode ini masih dapat digunakan sebagai referensi menerima untuk berinteraksi dengan—dan mungkin mengubah—objek asli. Demikian pula, ketika kembali informasi dari sebuah metode melalui pernyataan return, metode mengembalikan copy dari nilai yang disimpan dalam nilai-tipe variabel atau copy referensi yang tersimpan dalam referensi-jenis variabel. Ketika referensi kembali, memanggil metode dapat menggunakan referensi untuk berinteraksi dengan objek direferensikan. Jadi, pada dasarnya, benda-benda yang selalu dilalui referensi.
Dalam c#, untuk melewati sebuah variabel dengan referensi sehingga disebut method dapat memodifikasi variabel's, C# menyediakan kata kunci ref dan keluar. Menerapkan ref kata kunci untuk parameter deklarasi memungkinkan anda untuk melewati variabel metode dengan referensi—yang disebut metode akan dapat memodifikasi variabel asli di pemanggil. Ref kata kunci yang digunakan untuk variabel-variabel yang telah diinisialisasi dalam pemanggilan metode. Secara normal, ketika sebuah metode panggilan mengandung uninitialized variabel sebagai argumen, compiler akan menghasilkan error. Sebelumnya parameter dengan kata kunci out menciptakan output parameter. Ini menunjukkan kepada compiler bahwa argumen akan diteruskan ke yang disebut metode referensi dan bahwa yang disebut metode akan menetapkan nilai ke variabel asli di pemanggil. Jika metode ini tidak memberikan nilai pada parameter output di setiap jalan yang mungkin eksekusi, compiler akan menghasilkan error. Hal ini juga mencegah compiler menghasilkan pesan kesalahan untuk uninitialized variabel yang dilewatkan sebagai argumen untuk sebuah metode. Metode yang dapat mengembalikan hanya satu nilai ke pemanggil melalui pernyataan return, tetapi dapat mengembalikan banyak nilai-nilai dengan menentukan multiple output (ref dan/atau di luar) parameter.
melihat c# diskusi dan contoh-contoh berikut ini link text
Contoh:
const &
umumnya terbaik. Anda don't dikenakan konstruksi dan penghancuran penalti. Jika referensi isn't const anda antarmuka yang menunjukkan bahwa hal itu akan mengubah berlalu dalam data.Singkatnya, Lulus dengan nilai adalah APA itu dan berlalu dengan referensi adalah di MANA itu.
Jika anda nilai VAR1 = "Pria Bahagia!", anda hanya akan melihat "Pria Bahagia!". Jika VAR1 perubahan "Happy Gal!", anda memenangkan't tahu itu. Jika itu's disahkan oleh referensi, dan VAR1 perubahan, anda akan.
Jika anda don't ingin mengubah nilai dari variabel asli setelah melewati itu menjadi sebuah fungsi, fungsi tersebut harus dibangun dengan "lulus dengan nilai" parameter.
Maka fungsi HANYA akan memiliki nilai tetapi tidak alamat berlalu dalam variabel. Tanpa variabel's alamat, kode dalam fungsi tidak dapat mengubah nilai variabel seperti yang terlihat dari luar fungsi.
Tetapi jika anda ingin untuk memberikan fungsi kemampuan untuk mengubah nilai dari variabel seperti yang terlihat dari luar, anda perlu menggunakan pass by reference. Karena kedua nilai dan alamat (referensi) yang lulus dalam dan tersedia di dalam fungsi.
lulus dengan nilai yang berarti cara untuk lulus nilai untuk fungsi dengan memanfaatkan argumen. di lulus dengan nilai yang kita copy data yang disimpan dalam variabel yang kita tentukan, dan itu lebih lambat daripada lewat referensi bcse t data yang disalin . kami membuat perubahan dalam data yang disalin data asli tidak terpengaruh. nd di lewat refernce atau lewat alamat kami mengirim link langsung ke variabel itu sendiri . atau lewat pointer ke variabel. hal ini lebih cepat bcse waktu kurang dikonsumsi
Berikut adalah contoh yang menunjukkan perbedaan antara lulus dengan nilai - nilai pointer - referensi: