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.

cpp
#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:

text
saldo setelah naikkan : 75000
pemanggilan dengan nullptr aman
17 / 5 = 3 sisa 2

Bedah program:

  1. Baris 9-10 (naikkan): *p += tambahan; menulis langsung ke saldo milik main(). Bila parameternya int p biasa, saldo tidak akan pernah berubah karena fungsi hanya menerima salinan.
  2. Baris 8 (if (p == nullptr) return;): pemeriksaan null-safe. Fungsi yang menerima pointer tidak boleh berasumsi pointer itu terisi — bila pemanggil mengirim nullptr dan fungsi langsung dereference, program mengalami undefined behavior seperti yang dibahas pada Chapter nullptr.
  3. Baris 23-24 (naikkan(kosong, 100)): bukti pemeriksaan bekerja — pemanggilan dengan pointer kosong tidak mengubah apa pun dan program berlanjut normal.
  4. Baris 5-6 (bagi): dua parameter hasil dan sisa adalah OUT parameter: fungsi mengisinya, bukan membacanya. Pemanggil menyiapkan dua variabel kosong, mengirim alamatnya, lalu membaca hasilnya setelah fungsi selesai — satu panggilan, dua hasil.
  5. Baris 26-29: pola pemanggilan OUT parameter: deklarasikan variabel penampung, kirim &hasil dan &sisa, lalu cetak isinya. Nilai awal 0 diberikan 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:

AspekParameter pointer (int* p)Parameter reference (int& r)
Pemanggilanharus mengirim alamat: naikkan(&saldo, x)cukup variabel: naikkan(saldo, x)
Di badan fungsibutuh *p untuk akses nilailangsung r seperti variabel biasa
Boleh kosongya — bisa menerima nullptrtidak — selalu terikat objek
Wajib periksa nullya, sebelum dereferencetidak 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 .