Kenapa Konstanta Ada
Konstanta adalah nilai yang kamu janjikan tidak akan pernah berubah setelah kamu menetapkannya. Menandai sesuatu sebagai const melakukan dua tugas sekaligus: menjelaskan maksudmu kepada siapa pun yang membaca kode, dan membuat compiler menegakkan maksud itu. Setiap baris yang mencoba mengubah nilainya menjadi compile error, bukan bug diam-diam saat program berjalan.
Kalau kata kunci auto membiarkan compiler menyimpulkan tipe variabel, const membatasi apa yang bisa kamu lakukan dengan variabel itu. Keduanya bisa digabung dengan bebas: const auto limit = 100; adalah int yang read-only.
Mendeklarasikan Nilai const
Tulis const sebelum tipenya. Variabel const wajib diinisialisasi di baris yang sama, karena tidak ada momen lain ketika kamu boleh mengisinya.
Hapus tanda komentar pada baris pengisian itu dan programnya tidak akan bisa dikompilasi: compiler melaporkan "assignment of read-only variable". Justru itu intinya: kesalahannya tertangkap sebelum program sempat berjalan.
Kebiasaan pemula yang terbawa dari C adalah #define MAX_USERS 100. Hindari itu. Macro adalah penggantian teks secara buta tanpa tipe dan tanpa memedulikan scope, jadi ia tidak bisa diperiksa di debugger dan menghasilkan pesan error yang membingungkan. Variabel const (atau constexpr) dicek tipenya dan punya scope seperti variabel lainnya.
const vs constexpr
Kedua kata kunci memberimu nilai yang tidak bisa berubah, tetapi keduanya menjawab pertanyaan yang berbeda. const berkata "ini tidak pernah berubah setelah ditetapkan". constexpr berkata sesuatu yang lebih kuat: "ini bisa dihitung saat kompilasi", dan apa pun yang constexpr otomatis juga const.
Patokannya: pakai constexpr setiap kali nilainya berupa literal tetap atau perhitungan yang bisa dikerjakan compiler (ukuran array, panjang buffer, label switch, argumen template). Pakai const biasa kalau nilainya ditentukan saat program berjalan tetapi tidak boleh berubah sesudahnya, misalnya salinan const dari argumen fungsi.
Sejak C++20 ada juga consteval, yang dipakai pada fungsi yang wajib berjalan saat kompilasi:
consteval int square(int x) { return x * x; }
constexpr int area = square(8); // computed during compilation
Fungsi constexpr boleh berjalan saat kompilasi; fungsi consteval selalu harus begitu, kalau tidak hasilnya error.
Pointer dan const: Baca dari Kanan ke Kiri
Di sinilah const sering menjebak, karena kata kunci itu bisa berada di kedua sisi * dan kedua artinya berlawanan. Triknya adalah membaca deklarasi dari kanan ke kiri.
Baca int* const p2 dari kanan ke kiri: "p2 adalah const pointer ke int". Baca const int* p1 sebagai "p1 adalah pointer ke const int". Kalau salah membacanya, kamu akan menghabiskan banyak waktu kebingungan dengan error yang bilang kamu tidak boleh mengubah sesuatu yang kamu kira bisa diubah.
Satu jebakan praktis: jangan pernah mengambil alamat sebuah const lalu membuang const-nya lewat cast untuk mengubah objek aslinya. Itu adalah undefined behavior kalau objek aslinya memang const, dan compiler bebas menganggap nilainya tidak pernah berubah, sehingga "penulisan"-mu bisa saja diabaikan.
Referensi const sebagai Parameter Fungsi
Pemakaian const yang paling sering sehari-hari adalah meneruskan objek besar lewat referensi tanpa menyalinnya. Parameter const& menghindari salinan dan berjanji bahwa fungsi tidak akan mengubah argumen milik pemanggil.
Pass-by-const& adalah pilihan default untuk parameter apa pun yang lebih besar dari beberapa byte (string, vector, class buatanmu sendiri). Perhatikan juga bahwa ini membuat fungsi bisa menerima nilai sementara seperti "Grace". Referensi non-const biasa tidak bisa mengikat nilai sementara, jadi menghapus const di sini akan membuat panggilan kedua itu ditolak.
const Member Function
Saat menulis sebuah class, tandai setiap method yang tidak mengubah objek dengan const di akhir. Inilah yang membuat method itu bisa dipanggil pada instance const dan pada parameter const&. Tanpa itu, kamu tidak bisa membaca objekmu sendiri lewat pegangan const.
Disiplin menandai method read-only dengan const disebut const correctness. Biasakan sejak awal: membetulkan satu method yang seharusnya const itu mudah, tetapi memasang const belakangan di seluruh codebase yang besar itu menyakitkan, karena setiap pemanggil lewat referensi const bergantung padanya.
Berikutnya: Operator
Sekarang nilaimu sudah bisa dikunci dengan const, langkah berikutnya adalah melakukan sesuatu dengannya. Halaman operator membahas operator aritmetika, perbandingan, logika, dan penugasan, termasuk jebakan seputar pembagian bilangan bulat, prioritas operator, dan bagaimana const berinteraksi dengan operator penugasan yang tidak boleh kamu pakai.
Pertanyaan yang sering diajukan
Apa perbedaan const dan constexpr di C++?
const berarti nilainya tidak bisa berubah setelah diinisialisasi, tetapi nilai itu boleh dihitung saat program berjalan. constexpr lebih kuat: ia menjamin nilainya bisa dihitung saat kompilasi, sehingga bisa dipakai di tempat yang membutuhkan konstanta saat kompilasi (ukuran array, argumen template, label switch). Setiap objek constexpr juga const, tetapi tidak setiap objek const adalah constexpr.
Bagaimana cara mendeklarasikan konstanta di C++?
Tulis const sebelum tipenya dan beri nilai: const int maxUsers = 100;. Variabel const harus diinisialisasi saat dideklarasikan, karena kamu tidak akan pernah bisa mengisinya nanti. Untuk konstanta saat kompilasi, utamakan constexpr int maxUsers = 100;. Hindari macro #define gaya C lama, karena macro tidak punya tipe dan mengabaikan scope.
Apa arti const pointer di C++?
Tergantung di mana const berada. const int* p adalah pointer ke const: kamu bisa mengarahkan ulang p, tetapi tidak bisa mengubah *p. int* const p adalah const pointer: kamu bisa mengubah *p, tetapi tidak bisa mengarahkan ulang p. Baca deklarasinya dari kanan ke kiri: int* const adalah "const pointer ke int".