Menu

Reference C++: pass by reference, const&, dan alias

Reference di C++ dijelaskan: bagaimana & pada parameter membuat alias, kenapa pass by reference menghindari penyalinan dan membuat fungsi bisa mengubah variabel milik pemanggilnya, serta kapan memakai const& dan reference dibanding mengembalikan nilai.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Nama lain untuk hal yang sama

Di halaman parameter fungsi, setiap argumen disalin ke dalam fungsi. Penyalinan itulah alasan fungsi tidak bisa mengubah variabel milik pemanggil: ia hanya pernah melihat duplikatnya sendiri. Reference menembus batas itu. Reference adalah alias: nama kedua yang diikat ke variabel yang sudah ada, dan memakai memori yang persis sama.

Kamu membuat reference dengan & di deklarasi. Begitu terikat, reference dan variabel aslinya tidak bisa dibedakan:

Dua aturan membuat reference aman dan bisa ditebak: reference harus diinisialisasi saat dideklarasikan (int& r; adalah error kompilasi), dan setelahnya tidak pernah bisa diarahkan ulang ke hal lain. Mengisi nilai ke reference selalu menulis ke variabel yang diikatnya sejak awal.

Pass by reference: biarkan fungsi menjangkau balik

Manfaat sesungguhnya ada di fungsi. Tambahkan & pada sebuah parameter, maka fungsi menerima alias ke argumen milik pemanggil, bukan salinannya. Sekarang perubahan di dalam fungsi terlihat dari luar:

Hapus &, maka addBonus hanya akan menaikkan salinan sekali pakai, dan total tetap 100. Satu karakter itu adalah seluruh perbedaannya. Inilah cara standar untuk menulis fungsi yang menghasilkan lebih dari satu hasil atau mengubah input-nya di tempat. Contoh klasiknya adalah menukar dua variabel:

Tanpa reference, swapValues hanya akan menukar salinan lokal dan x/y tetap 1 2. (Library standar sudah punya std::swap, tapi menulisnya sendiri menunjukkan dengan jelas apa yang kamu dapat dari parameter reference.)

const reference: baca dengan cepat, janji tidak menyentuh

Pass by reference juga menghindari penyalinan, dan untuk objek besar penyalinan itu bisa mahal. Tapi parameter T& biasa memberi sinyal "aku mungkin mengubah ini", dan itu menyesatkan kalau kamu hanya ingin membaca. Solusinya adalah const T&: kamu mendapat kecepatan reference tanpa penyalinan dan janji yang dipastikan compiler bahwa fungsi tidak akan mengubah argumennya.

Reference non-const hanya bisa diikat ke variabel yang bisa diubah, tapi reference const juga bisa diikat ke literal dan objek sementara. Itulah sebabnya greet("literal works too") bisa dikompilasi. Aturan praktis untuk memilih tipe parameter:

void f(int x)              // cheap type, read-only -> just copy it
void f(const string& s)   // heavy type, read-only -> const reference
void f(string& s)         // you intend to modify the caller's object

Gunakan const T& sebagai default untuk tipe class apa pun yang hanya kamu baca (string, vector, struct buatanmu sendiri), dan simpan reference non-const untuk saat kamu memang ingin menulis balik.

Mengembalikan reference

Fungsi juga bisa mengembalikan reference, memberi pemanggil alias ke sesuatu yang sudah ada. Ini umum di kode yang mirip container: inilah yang membuat v[i] = 5 bisa bekerja, dan inilah yang dilakukan operator overloading di balik layar:

Karena at mengembalikan int&, ekspresi pemanggilan at(data, 1) itu sendiri adalah lvalue yang bisa diisi nilai. Kalau yang dikembalikan int biasa, at(data, 1) = 42 tidak akan bisa dikompilasi, karena kamu akan mengisi nilai ke salinan sementara.

Jebakan besar: dangling reference

Reference tidak memiliki apa pun; ia hanya menunjuk ke memori yang tinggal di tempat lain. Kalau memori itu mati saat reference masih dipakai, kamu punya dangling reference, dan membaca lewat reference itu adalah undefined behavior. Program bisa mencetak nilai sampah, crash, atau kelihatan berjalan sampai akhirnya merusak harimu di production. Kesalahan klasiknya adalah mengembalikan reference ke variabel lokal:

int& broken() {
    int local = 42;
    return local;   // BUG: local is destroyed when broken() returns
}                   // the returned reference dangles

int main() {
    int& r = broken();
    cout << r << "\n";   // UNDEFINED BEHAVIOR - reads dead memory
}

Variabel lokal local hilang begitu broken selesai, jadi reference-nya menunjuk ke ruang stack yang sudah diambil kembali. Kembalikan reference hanya ke sesuatu yang hidup lebih lama daripada pemanggilannya: parameter yang dikirim sebagai reference, data member, atau variabel static. Kalau nilainya dihitung di dalam fungsi, kembalikan berdasarkan nilai dan biarkan compiler mengoptimalkan penyalinannya. Jebakan yang sama berlaku untuk perulangan berbasis range dan setiap reference yang diikat ke objek sementara: jangan pernah menyimpan reference melewati masa hidup hal yang dirujuknya.

Berikutnya: function overloading

Reference memberimu pengaturan kedua di setiap parameter (salinan atau alias, bisa diubah atau const), dan pengaturan itu berhubungan langsung dengan topik berikutnya. Selanjutnya, function overloading memungkinkan kamu mendefinisikan beberapa fungsi dengan nama yang sama tapi daftar parameter yang berbeda, dan compiler memilih yang tepat dengan mencocokkan tipe argumennya, termasuk apakah argumen itu dikirim berdasarkan nilai, reference, atau reference const.

Pertanyaan yang sering diajukan

Apa itu reference di C++?

Reference adalah alias untuk variabel yang sudah ada, yaitu nama lain untuk memori yang sama. Kamu membuatnya dengan & di deklarasi: int& r = x;. Setelah itu, r dan x bisa dipertukarkan; mengubah salah satunya akan mengubah yang lain. Reference harus diinisialisasi saat dideklarasikan dan tidak pernah bisa diarahkan ulang untuk merujuk variabel lain.

Apa perbedaan pass by value dan pass by reference di C++?

Pass by value (void f(int x)) menyalin argumen, jadi fungsi bekerja dengan salinannya sendiri dan variabel milik pemanggil tidak tersentuh. Pass by reference (void f(int& x)) memberi fungsi akses langsung ke variabel milik pemanggil, jadi perubahannya terlihat setelah pemanggilan. Selain itu tidak ada penyalinan, dan itu penting untuk objek besar.

Kapan sebaiknya memakai parameter const reference di C++?

Pakai const T& kalau fungsi hanya perlu membaca parameternya tapi tipenya mahal untuk disalin (string, vector, struct besar). Kamu mendapat kecepatan reference tanpa penyalinan, plus jaminan dari compiler bahwa fungsi tidak akan mengubah nilai milik pemanggil. Untuk tipe murah seperti int atau double, pass by value biasa lebih sederhana dan sama cepatnya.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai