Chapter sebelumnya ditutup dengan peringatan: variabel tanpa nilai awal memuat nilai tak tentu. Solusinya adalah initialization — pemberian nilai pada saat variabel dideklarasikan — dan menariknya, C++ menyediakan tiga bentuk penulisan untuk itu. Ketiganya menghasilkan variabel yang sama-sama terisi, tetapi tidak sepenuhnya setara: satu bentuk di antaranya punya pengaman ekstra yang menolak konversi yang berisiko mengubah nilai. Pada Chapter ini kita mengenali ketiga bentuk tersebut, melihat perilaku khusus kurung kurawal kosong yang menjamin nilai nol, dan memahami mengapa gaya modern C++ menganjurkan kurung kurawal sebagai pilihan utama.
Tiga Bentuk Inisialisasi #
Program berikut mendeklarasikan variabel dengan isi yang sama persis, tetapi memakai tiga penulisan berbeda:
#include <iostream>
#include <string>
int main() {
int a = 10; // copy initialization: bentuk paling umum
int b(20); // direct initialization: memakai tanda kurung
int c{30}; // list initialization: kurung kurawal
int d{}; // list initialization kosong: dijamin bernilai nol
double beratKosong{}; // kurawal kosong pada double: dijamin 0.0
std::string s1 = "copy";
std::string s2("direct");
std::string s3{"list"};
std::cout << "a = " << a << ", b = " << b << ", c = " << c << ", d = " << d << "\n";
std::cout << "beratKosong = " << beratKosong << "\n";
std::cout << s1 << " / " << s2 << " / " << s3 << "\n";
return 0;
}Output yang Dihasilkan:
a = 10, b = 20, c = 30, d = 0
beratKosong = 0
copy / direct / listPembacaan baris demi baris:
- Baris 6 (
int a = 10;): copy initialization. Bentuk paling tua dan paling akrab, ditulis dengan tanda=seperti assignment biasa. - Baris 7 (
int b(20);): direct initialization. Nilai diberikan lewat tanda kurung setelah nama, mirip cara kita memanggil fungsi. - Baris 8-9: list initialization (juga sering disebut brace initialization). Nilai diletakkan di dalam kurung kurawal; bentuk kosong
{}tanpa nilai berarti “inisialisasi dengan nol”. - Baris 11 (
double beratKosong{};): bukti bahwa kurawal kosong berlaku untuk tipe apa pun — variabeldoubleini dijamin0.0.std::coutmenampilkannya sebagai0, karena format default menghilangkan angka nol di belakang koma. - Baris 13-15: ketiga bentuk inisialisasi juga berlaku untuk
std::string; pilihannya murni soal gaya, hasilnya identik.
Ketiga bentuk untuk tipe sederhana seperti int menghasilkan variabel yang sama persis. Perbedaan muncul pada dua situasi: ketika ada konversi tipe yang berisiko (dibahas sebentar lagi), dan ketika tipe kompleks seperti container memiliki constructor dengan jumlah argumen berbeda — topik yang akan masuk akal setelah kita mempelajari class.
Zero Initialization dengan Kurawal Kosong #
Bentuk int d{}; disebut zero initialization: compiler mengisi variabel dengan “nol” sesuai tipenya — 0 untuk integer, 0.0 untuk floating-point, false untuk bool, dan karakter \0 untuk char. Ini adalah jawaban langsung atas masalah Chapter sebelumnya: dengan satu karakter tambahan, kita mendapat jaminan variabel tidak memuat sisa memori. Bandingkan int d{}; yang pasti bernilai 0 dengan int d; yang isinya bisa apa saja.
Perlu dibedakan dari deklarasi int d; yang diberi nilai lewat assignment sesudahnya. Zero initialization terjadi pada saat deklarasi, tanpa pernyataan terpisah, sehingga tidak ada celah baris di mana variabel berstatus “belum berisi”. Untuk variabel yang memang akan segera diisi, bentuk kosong ini juga menjadi penanda yang jelas bahwa nol adalah nilai awal yang disengaja.
Pengaman Narrowing dari Kurung Kurawal #
Perbedaan paling penting antar ketiga bentuk muncul saat nilai awal butuh konversi narrowing — konversi yang berpotensi mengubah nilai karena targetnya lebih kecil. Bentuk = dan tanda kurung membiarkan konversi seperti itu terjadi tanpa suara; kurung kurawal menolaknya keras. Lihat dua baris berikut:
int lebar = 3.14; // lolos: 3.14 dipotong diam-diam menjadi 3
int lebarLain{3.14}; // DITOLAK compiler
Baris pertama dikompilasi tanpa keluhan, padahal 3.14 kehilangan pecahannya dan tersisa 3 — bug yang halus karena tidak ada jejak di output. Baris kedua gagal kompilasi dengan pesan yang jelas:
nar-demo.cpp:2:15: error: narrowing conversion of ‘3.1400000000000001e+0’ from ‘double’ to ‘int’ [-Wnarrowing]
2 | int lebarLain{3.14}; // DITOLAK compiler
| ^~~~Compiler bahkan menunjukkan nilai double aslinya secara persis (3.1400000000000001e+0) sebelum ditolak. Dengan kurung kurawal, kesalahan ketik atau salah hitung yang tadinya menumpuk diam-diam berubah menjadi pesan error di saat kompilasi — jauh lebih murah daripada dicari saat program sudah berjalan. Seluruh aturan narrowing, termasuk pengecualian untuk konstanta yang nilainya pas, kita bedah tuntas pada Chapter Narrowing Conversion.
Dengan tiga bentuk inisialisasi di tangan, kita sudah bisa menulis variabel yang aman. Namun ada satu aturan lain yang berlaku sebelum variabel boleh ada: nama yang kita pilih harus sah menurut standar bahasa. Itulah bahan Chapter berikutnya — aturan penamaan identifier, kata kunci yang tidak boleh dipakai, dan konvensi yang membuat kode enak dibaca.
Rujukan resmi untuk topik Chapter ini: initialization dan list initialization di cppreference.