Chapter sebelumnya menutup dengan pertanyaan: bagaimana cara menyimpan sebuah alamat memori? Jawabannya adalah pointer — variabel yang nilainya bukan data biasa, melainkan alamat tempat data lain berada. Kita bisa menganggap pointer sebagai kertas bertuliskan nomor rumah: isi kertasnya bukan rumah itu sendiri, tetapi cukup untuk menemukan rumah tersebut. Pointer adalah salah satu fitur paling khas C++: ia memberi kita kontrol langsung atas memori, dan hampir semua konsep lanjutan (array dinamis, iterator, smart pointer, polymorphism) berdiri di atas fondasi ini.

Deklarasi dan Inisialisasi Pointer #

Deklarasi pointer ditulis dengan tanda * di antara tipe dan nama variabel. Perhatikan kata “bertipe”: pointer selalu memiliki tipe sasaran, dan itulah kunci keamanannya.

cpp
#include <iostream>

int main() {
    int nilai = 50;
    double ipk = 3.75;

    int* p = &nilai;     // pointer bertipe int, menunjuk variabel nilai
    double* q = &ipk;    // pointer bertipe double, menunjuk variabel ipk

    std::cout << "Nilai via variabel : " << nilai << "\n";
    std::cout << "Nilai via *p       : " << *p << "\n";
    std::cout << "Nilai via *q       : " << *q << "\n";

    // Pointer juga variabel biasa: sasarannya boleh diganti
    int lain = 99;
    p = &lain;
    std::cout << "Setelah p = &lain  : " << *p << "\n";

    // Ukuran semua pointer sama pada satu platform (di sini: 64-bit)
    std::cout << "sizeof(int*)    : " << sizeof(int*) << " byte\n";
    std::cout << "sizeof(double*) : " << sizeof(double*) << " byte\n";

    return 0;
}

Output yang Dihasilkan:

text
Nilai via variabel : 50
Nilai via *p       : 50
Nilai via *q       : 3.75
Setelah p = &lain  : 99
sizeof(int*)    : 8 byte
sizeof(double*) : 8 byte

Mari kita telaah bagian-bagian pentingnya:

  1. Baris 6-7 (int* p = &nilai;): p dideklarasikan sebagai pointer ke int, lalu langsung diisi alamat nilai. Gaya penulisan int* p dan int *p sama-sama sah; yang penting konsisten. Satu jebakan sintaks: int* a, b; hanya membuat a menjadi pointer — b tetap int biasa. Deklarasikan satu pointer per baris untuk menghindari kebingungan ini.
  2. Baris 10-12 (*p, *q): tanda * di depan nama pointer berarti “baca nilai yang ditunjuk” (dereference). *p bernilai 50, persis seperti membaca nilai langsung. Pembahasan penuhnya ada pada Chapter Dereferencing.
  3. Baris 16-17 (p = &lain;): pointer adalah variabel, sehingga isinya bisa diganti. Setelah baris ini, p tidak lagi menunjuk nilai, melainkan lain — buktinya *p sekarang bernilai 99.
  4. Baris 20-21 (sizeof ...): semua pointer — ke int, ke double, ke tipe apa pun — berukuran sama (8 byte pada platform 64-bit), karena semua alamat di ruang memori yang sama punya panjang seragam. Yang membedakan pointer bukan ukurannya, melainkan tipe sasarannya.

Mengapa Pointer Harus Bertipe #

Compiler memakai tipe pointer untuk dua hal: memeriksa kesalahan saat kompilasi dan mengetahui berapa byte yang harus dibaca ketika kita melakukan dereference. Bila kita mencoba menampung alamat double di dalam pointer int, compiler menolaknya:

cpp Kode yang ditolak compiler
int nilai = 50;
double ipk = 3.75;
double* q = &ipk;
int* p = &nilai;
p = q;  // mencoba mengisi pointer int dengan alamat double
text Pesan galat g++ 14.2
error: cannot convert 'double*' to 'int*' in assignment

Pesan cannot convert 'double*' to 'int*' muncul karena double* dan int* adalah tipe yang berbeda. Perlakuan ketat ini melindungi kita: tanpa aturan tersebut, satu dereference pada p bisa membaca 4 byte dari objek yang seharusnya dibaca 8 byte, dan hasilnya tidak berarti apa-apa. Konversi eksplisit antar-tipe pointer memang ada (misalnya reinterpret_cast yang sekilas kita pakai di Chapter Alamat Memori), tetapi digunakan hanya pada situasi khusus yang sengaja dipilih.

Pointer Kosong: Kenalan Dini #

Ada satu nilai khusus yang boleh diberikan ke pointer tipe apa pun: nullptr, yang berarti “pointer ini tidak menunjuk apa-apa”. int* p = nullptr; adalah cara mendeklarasikan pointer yang belum punya sasaran — dan jauh lebih aman daripada membiarkan pointer berisi alamat acak. Karena topiknya penting dan penuh detail, nullptr mendapat Chapter tersendiri yang langsung menyusul setelah kita membahas dereferencing.

Sekarang kita tahu cara menyimpan alamat dan menggantinya. Pertanyaan berikutnya: apa yang bisa kita lakukan dengan nilai yang tersimpan di alamat itu? Di sinilah dereferencing masuk — operasi membaca dan menulis melalui pointer.

Referensi: cppreference — pointer declaration , cppreference — nullptr .