Kata kunci const yang sudah kita kuasai pada Chapter const dan constexpr menjadi lebih bernuansa saat digabung dengan pointer, karena pointer punya dua hal yang bisa dikunci: isi pointer (alamat yang disimpan) dan nilai objek yang ditunjuknya. Mengunci salah satunya, keduanya, atau tidak sama sekali menghasilkan tiga bentuk deklarasi yang tampak mirip tetapi berbeda perilaku. Chapter ini membedah ketiganya dan memberi kita satu trik membaca yang andal: membaca deklarasi dari kanan ke kiri.

Pointer to Const: Nilai Terkunci, Pointer Bebas #

Deklarasi const int* pc membuat objek yang ditunjuk tidak boleh diubah melalui pointer ini, sementara pc tetap boleh berpindah menunjuk objek lain.

cpp
#include <iostream>

int main() {
    int a = 10;
    int b = 20;

    // 1. pointer to const: nilai lewat pointer tidak boleh diubah,
    //    tetapi pointer boleh berpindah sasaran
    const int* pc = &a;
    std::cout << "*pc awal : " << *pc << "\n";
    pc = &b;                 // sah: pointer berpindah
    std::cout << "*pc baru : " << *pc << "\n";
    b = 55;                  // sah: diubah lewat jalur non-const (variabel b)
    std::cout << "b = 55 -> *pc : " << *pc << "\n";

    // 2. const pointer: pointer terkunci pada satu sasaran,
    //    tetapi nilai sasarannya boleh diubah
    int* const cp = &a;
    *cp = 77;                // sah: mengubah nilai a
    std::cout << "*cp setelah *cp = 77 : " << *cp << "\n";

    // 3. const pointer to const: pointer dan nilai sama-sama terkunci
    const int* const cpc = &b;
    std::cout << "*cpc : " << *cpc << "\n";

    return 0;
}

Output yang Dihasilkan:

text
*pc awal : 10
*pc baru : 20
b = 55 -> *pc : 55
*cp setelah *cp = 77 : 77
*cpc : 55

Bagian yang penting kita pahami:

  1. Baris 11-13 (pc = &b;): pc berpindah dari a ke b tanpa keluhan — inilah kebebasan yang masih dimiliki pointer to const. *pc kini bernilai 20.
  2. Baris 14-15 (b = 55;): nilai di balik *pc berubah menjadi 55, tetapi bukan lewat pc. Objek b sendiri tidak konst, jadi mengubahnya langsung sah. const int* hanya mengunci jalur akses lewat pointer tersebut — fakta yang sering mengejutkan pemula.
  3. Baris 19-21 (int* const cp = &a;): posisi const setelah * mengunci pointer. *cp = 77 sah karena nilai boleh diubah, tetapi cp tidak akan pernah bisa menunjuk b.
  4. Baris 24-25 (const int* const cpc): kedua const dipasang, keduanya terkunci: nilai tidak bisa diubah lewat cpc, dan cpc tidak bisa berpindah.

Membaca Deklarasi dari Kanan ke Kiri #

Cara menentukan makna deklarasi pointer-const apa pun: mulai dari nama variabel, lalu baca ke kanan dulu, baru ke kiri. Tabel berikut merangkum tiga bentuknya:

DeklarasiDibaca dari kanan ke kiriPointer berpindah?Nilai lewat pointer diubah?
const int* pc“pc adalah pointer ke int yang const”bisatidak bisa
int* const cp“cp adalah pointer const ke int”tidak bisabisa
const int* const cpc“cpc adalah pointer const ke int yang const”tidak bisatidak bisa

Trik praktisnya: posisi const sebelum * mengunci nilai (pointer to const); posisi const sesudah * mengunci pointer (const pointer). Bentuk yang sama dengan int const* pc — const sebelum int atau sesudahnya — bermakna identik; yang menentukan adalah posisinya relatif terhadap *.

Pelanggarannya Terdeteksi saat Kompilasi #

Keunggulan terbesar const adalah setiap pelanggaran ditangkap compiler, jauh sebelum program dijalankan. Potongan berikut memakai kembali variabel di atas:

cpp Kode yang ditolak compiler
*pc = 99;   // nilai terkunci lewat pointer to const
cp = &b;    // pointer const tidak boleh berpindah
text Pesan galat g++ 14.2
error: assignment of read-only location '* pc'
error: assignment of read-only variable 'cp'

Dua pesan read-only itu jelas menyebut apa yang dilanggar: lokasi yang dibaca-saja pada kasus pertama, variabel yang dibaca-saja (pointer cp) pada kasus kedua. Perhatikan bahwa pelanggaran seperti ini tidak mungkin lolos menjadi bug runtime — inilah alasan menambahkan const semampu kita disebut “murah” dan sangat dianjurkan.

Kapan Memakai yang Mana #

Pilihan bentuknya mengikuti niat kita:

  • const T* p (paling sering): fungsi menerima objek lewat pointer tetapi berjanji tidak mengubahnya — seperti parameter const int* arr pada Chapter sebelumnya. Juga lazim untuk membaca data yang sebaiknya tidak tersentuh.
  • T* const p: pointer yang tidak boleh kehilangan sasarannya, misalnya penunjuk tetap ke buffer atau konfigurasi yang diset sekali saat inisialisasi. Padanannya yang lebih modern dan lebih disukai: cukup pakai reference atau constexpr.
  • const T* const p: kombinasi keduanya, untuk data yang benar-benar dibaca-saja lewat satu penunjuk tetap.

Kita kini menguasai pointer dalam segala variasi konstnya. Saatnya memakainya di tempat yang paling sering ditemui programmer: sebagai parameter fungsi — membawa nilai keluar dari fungsi, bukan hanya masuk.

Referensi: cppreference — cv qualifier (const) , cppreference — pointer .