Pada Chapter sebelumnya kita mendeklarasikan array lalu mengisinya satu per satu — sah, tetapi melelahkan untuk lima elemen, apalagi lima puluh. C++ menyediakan cara yang jauh lebih ringkas: initializer list, yaitu daftar nilai di dalam kurung kurawal yang ditulis langsung saat deklarasi. Selain meringkas kode, inisialisasi menyelesaikan masalah serius dari Chapter sebelumnya: array lokal yang tidak diinisialisasi berisi sampah memori. Pada Chapter ini kita mempelajari bentuk-bentuk inisialisasi array, aturan otomatisnya untuk elemen yang tidak diisi, dan cara meminta compiler menebak ukurannya.
Initializer List: Empat Bentuk yang Sering Dipakai #
Cara paling umum mengisi array adalah menuliskan nilainya langsung dalam kurung kurawal. Program berikut memuat empat variasi yang perlu kita kuasai:
#include <iostream>
int main() {
int penuh[5] = {1, 2, 3, 4, 5}; // diisi lengkap
int sebagian[5] = {10, 20}; // dua nilai; sisanya otomatis 0
int kosong[5] = {}; // semuanya di-nol-kan
int otomatis[] = {7, 14, 21}; // ukuran dideduksi compiler: 3 elemen
// (i > 0 ? " " : "") menyisipkan spasi hanya di antara elemen
std::cout << "penuh : ";
for (int i = 0; i < 5; ++i)
std::cout << (i > 0 ? " " : "") << penuh[i];
std::cout << "\nsebagian: ";
for (int i = 0; i < 5; ++i)
std::cout << (i > 0 ? " " : "") << sebagian[i];
std::cout << "\nkosong : ";
for (int i = 0; i < 5; ++i)
std::cout << (i > 0 ? " " : "") << kosong[i];
std::cout << "\notomatis: ";
for (std::size_t i = 0; i < sizeof(otomatis) / sizeof(otomatis[0]); ++i)
std::cout << (i > 0 ? " " : "") << otomatis[i];
std::cout << "\notomatis berisi "
<< sizeof(otomatis) / sizeof(otomatis[0]) << " elemen\n";
return 0;
}Output yang Dihasilkan:
penuh : 1 2 3 4 5
sebagian: 10 20 0 0 0
kosong : 0 0 0 0 0
otomatis: 7 14 21
otomatis berisi 3 elemenMari kita bedah kode di atas:
- Baris 4 (
int penuh[5] = {1, 2, 3, 4, 5};): jumlah nilai sama dengan ukuran array, sehingga setiap slot mendapat nilai eksplisit secara berurutan. Bentuk ini paling jelas dibaca. - Baris 5 (
int sebagian[5] = {10, 20};): hanya dua nilai pertama yang diberi data. Standar C++ menentukan aturan yang konsisten: elemen yang tidak diisi otomatis di-nol-kan, sehinggasebagianberisi10 20 0 0 0— bukan sampah memori. - Baris 6 (
int kosong[5] = {};): kurung kurawal kosong berarti “nol-kan semua elemen”. Bentuk ini paling aman dipakai ketika kita belum punya data, karena array langsung bersih dari nilai acak. - Baris 7 (
int otomatis[] = {7, 14, 21};): tanda kurung siku boleh dibiarkan kosong bila ada initializer list — compiler menebak ukurannya dari jumlah nilai, yaitu 3. Hasil deduksinya bisa kita buktikan lewatsizeof(otomatis) / sizeof(otomatis[0])yang dievaluasi di baris 21-22. - Baris 11-12 (
(i > 0 ? " " : "")): pola pemisah output — spasi hanya dicetak di antara dua elemen, sehingga setiap baris tidak berakhir dengan spasi menggantung. Pola kecil ini sering berguna saat kita mencetak isi koleksi.
Ukuran Harus Konstanta Waktu Kompilasi #
Ukuran array C-style ditentukan compiler pada saat kompilasi, karena compiler harus memesan blok memori dengan ukuran pasti sebelum program berjalan. Akibatnya, ukuran tersebut harus berupa constant expression — nilai yang diketahui saat kompilasi, misalnya angka langsung, konstanta const int, atau constexpr int. Nilai yang baru diketahui saat program berjalan (misalnya dari input pengguna) tidak boleh dipakai sebagai ukuran array C-style.
Kode berikut gagal dikompilasi. Kita uji dengan flag -pedantic-errors agar pelanggaran standar ditandai sebagai error, bukan sekadar peringatan:
#include <iostream>
int main() {
int n = 5;
int data[n]; // SALAH: ukuran array harus konstanta waktu kompilasi
data[0] = 1;
std::cout << data[0] << "\n";
return 0;
}Output yang Dihasilkan:
ukuran-dinamis.cpp: In function 'int main()':
ukuran-dinamis.cpp:5:9: error: ISO C++ forbids variable length array 'data' [-Wvla]
5 | int data[n]; // SALAH: ukuran array harus konstanta waktu kompilasi
| ^~~~Pesan ISO C++ forbids variable length array muncul karena beberapa compiler (termasuk GCC) membolehkan variable length array sebagai ekstensi non-standar; flag -pedantic-errors memaksa compiler tunduk pada standar C++ murni. Solusi yang sah ada dua: gunakan konstanta seperti constexpr int n = 5;, atau — bila ukurannya memang baru diketahui saat runtime — pakai std::vector yang dibahas pada Chapter berjudul std::vector.
Perhatikan pula bahwa ukuran array tidak boleh negatif dan tidak boleh nol: int data[0]; ditolak compiler. Ekspresi ukuran juga dievaluasi saat kompilasi, sehingga constexpr adalah kata kunci yang tepat untuk memberi nama ukuran yang sering dipakai:
constexpr int jumlahSiswa = 30; // konstanta waktu kompilasi
int nilai[jumlahSiswa] = {}; // sah: 30 elemen, semua 0
Memilih Bentuk Inisialisasi yang Tepat #
Ketiga sumber di atas saling melengkapi. Tabel berikut merangkum kapan masing-masing bentuk paling cocok:
| Situasi | Bentuk yang disarankan | Alasan |
|---|---|---|
| Data sudah diketahui saat menulis kode | int a[5] = {1, 2, 3, 4, 5}; | Nilai terlihat jelas dan urut |
| Bagian awal berbeda, sisanya nol | int a[5] = {10, 20}; | Aturan “sisanya nol” menghemat penulisan |
| Array dipakai sebagai wadah kerja | int a[5] = {}; | Terbebas dari sampah memori |
| Tidak ingin menghitung elemen manual | int a[] = {1, 2, 3}; | Compiler menebak ukuran dari jumlah nilai |
Satu catatan terakhir tentang type safety: compiler juga memeriksa jumlah nilai. int a[3] = {1, 2, 3, 4}; ditolak karena ada empat nilai untuk tiga slot — initializer list tidak pernah diam-diam memotong data. Kelebihan ini hilang ketika kita mengisi elemen lewat loop, sehingga disiplin indeks dari Chapter Mengakses Elemen Array tetap diperlukan.
Chapter berikutnya mengintensifkan diskusi indeks: cara membaca dan mengubah elemen dengan aman, dan mengapa mengakses di luar batas adalah undefined behavior yang harus kita hindari dengan pola penulisan yang benar.
Rujukan resmi: cppreference — Declarations: Array (Initialization) .