Secara default, C++ meneruskan argumen ke fungsi dengan pass-by-value: fungsi menerima salinan, dan mengubah salinan tidak berdampak apa pun pada variabel pemanggil. Pointer memecahkan batasan itu — kita mengirim alamat variabel, sehingga fungsi dapat mengunjungi dan mengubah objek aslinya melalui dereference. Pola ini juga membuka kemampuan baru: satu fungsi dapat “mengembalikan” lebih dari satu hasil melalui parameter yang ditulis oleh fungsi. Chapter ini melatih kedua pola tersebut sekaligus kewajiban pemeriksaan null di dalam fungsi.
Mengubah Nilai Asli lewat Pointer #
Ketika fungsi menerima int* p, ia menerima salinan alamat — tetapi alamat yang disalin tetap menunjuk objek asli di pemanggil. Dereference di dalam fungsi berarti menyentuh objek itu langsung.
#include <iostream>
// Dua OUT parameter: hasil ditulis melalui pointer yang dikirim caller
void bagi(int a, int b, int* hasil, int* sisa) {
if (hasil != nullptr) *hasil = a / b;
if (sisa != nullptr) *sisa = a % b;
}
// Mengubah nilai asli lewat pointer, dengan pemeriksaan null-safe
void naikkan(int* p, int tambahan) {
if (p == nullptr) return; // pointer kosong: tidak ada yang diubah
*p += tambahan;
}
int main() {
int saldo = 50000;
naikkan(&saldo, 25000);
std::cout << "saldo setelah naikkan : " << saldo << "\n";
int* kosong = nullptr;
naikkan(kosong, 100); // aman: fungsi memeriksa nullptr lebih dulu
std::cout << "pemanggilan dengan nullptr aman\n";
int hasil = 0;
int sisa = 0;
bagi(17, 5, &hasil, &sisa);
std::cout << "17 / 5 = " << hasil << " sisa " << sisa << "\n";
return 0;
}Output yang Dihasilkan:
saldo setelah naikkan : 75000
pemanggilan dengan nullptr aman
17 / 5 = 3 sisa 2Bedah program:
- Baris 9-10 (
naikkan):*p += tambahan;menulis langsung kesaldomilikmain(). Bila parameternyaint pbiasa,saldotidak akan pernah berubah karena fungsi hanya menerima salinan. - Baris 8 (
if (p == nullptr) return;): pemeriksaan null-safe. Fungsi yang menerima pointer tidak boleh berasumsi pointer itu terisi — bila pemanggil mengirimnullptrdan fungsi langsung dereference, program mengalami undefined behavior seperti yang dibahas pada Chapter nullptr. - Baris 23-24 (
naikkan(kosong, 100)): bukti pemeriksaan bekerja — pemanggilan dengan pointer kosong tidak mengubah apa pun dan program berlanjut normal. - Baris 5-6 (
bagi): dua parameterhasildansisaadalah OUT parameter: fungsi mengisinya, bukan membacanya. Pemanggil menyiapkan dua variabel kosong, mengirim alamatnya, lalu membaca hasilnya setelah fungsi selesai — satu panggilan, dua hasil. - Baris 26-29: pola pemanggilan OUT parameter: deklarasikan variabel penampung, kirim
&hasildan&sisa, lalu cetak isinya. Nilai awal0diberikan agar variabel tidak berisi sampah bila fungsi memutuskan tidak mengisinya.
Pola OUT Parameter #
Pola bagi(hasil, sisa) di atas punya nama resmi: parameter output (OUT parameter). Ia dipakai ketika fungsi perlu menghasilkan lebih dari satu nilai, atau ketika hasil utamanya sudah terpakai sebagai nilai kembalian. Konvensi penamaan yang membantu: urutkan parameter input lebih dulu, letakkan OUT parameter di belakang, dan beri nama yang mengarah ke isian (hasil, sisa, ukuran), bukan ke sumber (data, masukan).
Kekurangannya juga perlu kita sadari: pada baris pemanggil, bagi(17, 5, &hasil, &sisa) tidak terlihat variabel mana yang diubah — tanda & wajib kita baca sekalian dengan deklarasi fungsinya. Keramaian tanda & dan * inilah yang membuat banyak programmer lebih menyukai reference untuk peran yang sama.
Pointer versus Reference sebagai Parameter #
Keduanya membuat fungsi bisa mengubah objek asli pemanggil. Perbedaannya ada di batas-batas dan kesan pemanggilannya:
| Aspek | Parameter pointer (int* p) | Parameter reference (int& r) |
|---|---|---|
| Pemanggilan | harus mengirim alamat: naikkan(&saldo, x) | cukup variabel: naikkan(saldo, x) |
| Di badan fungsi | butuh *p untuk akses nilai | langsung r seperti variabel biasa |
| Boleh kosong | ya — bisa menerima nullptr | tidak — selalu terikat objek |
| Wajib periksa null | ya, sebelum dereference | tidak perlu |
| Sinyal kepada pembaca | “bisa kosong / bisa diubah / sasaran bisa berganti” | “wajib terisi, kebanyakan berarti diubah” |
Aturan memilihnya ringkas: pakai reference bila parameter wajib ada dan kehadirannya tidak berubah-ubah; pakai pointer justru bila kosong adalah keadaan yang bermakna — misalnya pilihan konfigurasi opsional, atau hasil pencarian yang mungkin tidak ditemukan. Pointer yang dikirim ke fungsi juga bisa disimpan untuk digunakan kembali setelah fungsi selesai, sesuatu yang reference tidak bisa tawarkan dengan jaminan yang sama.
Fungsi mengubah pointer kini sudah kita kuasai. Pertanyaan lanjutan yang menarik: bagaimana bila yang ingin diubah justru isi pointer milik pemanggil — alias pointer yang menunjuk pointer? Itu pekerjaan pointer-to-pointer.
Referensi: cppreference — function declaration , cppreference — pointer .