Ada beberapa perbedaan dalam konvensi pemanggilan di C ++ dan Java. Dalam C ++, secara teknis hanya ada dua konvensi: pass-by-value dan pass-by-reference, dengan beberapa literatur termasuk konvensi pass-by-pointer ketiga (yang sebenarnya pass-by-value dari tipe pointer). Di atas semua itu, Anda bisa menambahkan konstanta pada tipe argumen, meningkatkan semantik.
Lewati dengan referensi
Melewati dengan referensi berarti bahwa fungsi tersebut secara konseptual akan menerima instance objek Anda dan bukan salinannya. Referensi secara konseptual merupakan alias untuk objek yang digunakan dalam konteks panggilan, dan tidak bisa nol. Semua operasi yang dilakukan di dalam fungsi berlaku untuk objek di luar fungsi. Konvensi ini tidak tersedia di Jawa atau C.
Pass by value (dan pass-by-pointer)
Kompiler akan menghasilkan salinan objek dalam konteks panggilan dan menggunakan salinan itu di dalam fungsi. Semua operasi yang dilakukan di dalam fungsi dilakukan untuk menyalin, bukan elemen eksternal. Ini adalah konvensi untuk tipe primitif di Jawa.
Versi khusus itu lewat pointer (alamat-objek) ke fungsi. Fungsi menerima pointer, dan setiap dan semua operasi yang diterapkan pada pointer itu sendiri diterapkan ke copy (pointer), di sisi lain, operasi yang diterapkan pada pointer dereferenced akan berlaku untuk instance objek di lokasi memori itu, sehingga fungsi dapat memiliki efek samping. Efek menggunakan nilai pass-by-pointer ke objek akan memungkinkan fungsi internal untuk memodifikasi nilai-nilai eksternal, seperti dengan pass-by-reference dan juga akan memungkinkan untuk nilai-nilai opsional (melewati pointer nol).
Ini adalah konvensi yang digunakan dalam C ketika suatu fungsi perlu memodifikasi variabel eksternal, dan konvensi yang digunakan di Jawa dengan tipe referensi: referensi disalin, tetapi objek yang dirujuk adalah sama: perubahan pada referensi / penunjuk tidak terlihat di luar fungsi, tetapi perubahan memori menunjuk.
Menambahkan const ke persamaan
Dalam C ++ Anda dapat menetapkan konstan-objek untuk objek ketika mendefinisikan variabel, pointer dan referensi pada level yang berbeda. Anda dapat mendeklarasikan variabel sebagai konstan, Anda dapat mendeklarasikan referensi ke instance konstan, dan Anda dapat mendefinisikan semua pointer ke objek konstan, pointer konstan ke objek yang bisa berubah dan pointer konstan ke elemen konstan. Sebaliknya di Jawa, Anda hanya dapat menentukan satu tingkat kekenyalan (kata kunci akhir): variabel (contoh untuk tipe primitif, referensi untuk tipe referensi), tetapi Anda tidak dapat menentukan referensi ke elemen yang tidak dapat diubah (kecuali kelas itu sendiri adalah kekal).
Ini banyak digunakan dalam konvensi pemanggilan C ++. Ketika objek kecil, Anda bisa melewati objek dengan nilai. Kompiler akan menghasilkan salinan, tetapi salinan itu bukan operasi yang mahal. Untuk jenis lain, jika fungsi tidak akan mengubah objek, Anda dapat meneruskan referensi ke instance konstan (biasanya disebut referensi konstan) dari tipe tersebut. Ini tidak akan menyalin objek, tetapi meneruskannya ke fungsi. Tetapi pada saat yang sama kompiler akan menjamin bahwa objek tidak berubah di dalam fungsi.
Aturan praktis
Ini adalah beberapa aturan dasar yang harus diikuti:
- Lebih suka pass-by-value untuk tipe primitif
- Lebih suka pass-by-reference dengan referensi ke konstanta untuk tipe lain
- Jika fungsi perlu mengubah argumen, gunakan pass-by-reference
- Jika argumennya opsional, gunakan pass-by-pointer (untuk konstan jika nilai opsional tidak boleh dimodifikasi)
Ada penyimpangan kecil lainnya dari aturan ini, yang pertama adalah menangani kepemilikan suatu objek. Ketika suatu objek dialokasikan secara dinamis dengan yang baru, itu harus dialokasikan dengan menghapus (atau versi [] daripadanya). Objek atau fungsi yang bertanggung jawab atas penghancuran objek dianggap sebagai pemilik sumber daya. Ketika objek yang dialokasikan secara dinamis dibuat dalam sepotong kode, tetapi kepemilikan ditransfer ke elemen yang berbeda itu biasanya dilakukan dengan semantik pass-by-pointer, atau jika mungkin dengan smart pointer.
Catatan samping
Penting untuk menekankan pentingnya perbedaan antara C ++ dan referensi Java. Dalam C ++ referensi secara konseptual adalah instance dari objek, bukan accessor untuk itu. Contoh paling sederhana adalah menerapkan fungsi swap:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
Fungsi swap di atas mengubah kedua argumennya melalui penggunaan referensi. Kode terdekat di Jawa:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
Versi kode Java akan memodifikasi salinan referensi secara internal, tetapi tidak akan memodifikasi objek aktual secara eksternal. Referensi Java adalah pointer C tanpa aritmatika pointer yang diteruskan oleh nilai ke dalam fungsi.