Menu

vector C++: array dinamis dengan std::vector dijelaskan

std::vector adalah array C++ yang ukurannya bisa berubah, container yang sebaiknya kamu pakai secara default. Pelajari cara membuat, mengakses, memperbesar, dan menelusuri vector, plus jebakan iterator invalidation dan akses di luar batas.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Kenapa vector, bukan array biasa

Array biasa punya ukuran tetap yang ditentukan saat kompilasi, dan lupa panjangnya sendiri begitu kamu mengirimnya ke sebuah fungsi. std::vector menyelesaikan kedua masalah itu: ia adalah array yang ukurannya bisa berubah, mencatat panjangnya sendiri, membesar saat dibutuhkan, dan membersihkan memorinya sendiri. Di C++ modern, vector adalah container default. Pakai array biasa hanya kalau kamu punya alasan khusus.

Sertakan <vector>, lalu deklarasikan dengan tipe elemennya di dalam kurung siku:

scores.size() selalu memberi tahu panjangnya saat ini: tidak perlu int n terpisah yang harus terus disamakan, dan tidak perlu trik sizeof. {90, 75, 100, 60} adalah brace initializer; vector itu sendiri yang tahu bahwa ia butuh empat slot.

Membuat dan menginisialisasi vector

Ada beberapa cara untuk membuatnya, tergantung apa yang sudah kamu ketahui di awal:

Waspadai jebakan kurung biasa vs kurung kurawal: vector<int> tens(5, 10) membuat lima salinan 10, sedangkan vector<int> tens{5, 10} membuat vector dua elemen yang berisi 5 dan 10. Kurung biasa berarti "ukuran dan nilai pengisi"; kurung kurawal berarti "elemen-elemen literal ini".

Menambah dan menghapus elemen

Inti dari vector adalah ia bisa membesar. push_back menambahkan ke akhir, dan pop_back menghapus dari akhir:

back() mengembalikan elemen terakhir dan front() elemen pertama, lebih rapi daripada v[v.size() - 1] dan v[0]. Sejak C++11 kamu juga bisa memakai emplace_back(args...) untuk membuat elemen langsung di tempatnya, sehingga tidak ada salinan sementara untuk tipe yang lebih berat.

Kesalahan pemula yang umum adalah memanggil front() atau back() pada vector yang kosong. Itu undefined behavior, bukan error, jadi selalu lindungi dengan if (!v.empty()) lebih dulu.

Membaca elemen: [] vs at()

Kamu mengakses vector dengan indeks persis seperti array, memakai []. Tapi [] tidak mengecek batas: indeks di luar rentang adalah undefined behavior, yang bisa diam-diam membaca nilai sampah atau crash belakangan di tempat yang membingungkan:

vector<int> v = {1, 2, 3};
cout << v[10];   // UNDEFINED BEHAVIOR - no check, no error

Kalau kamu ingin aman, pakai at(). Ia mengecek indeksnya dan melempar std::out_of_range saat aksesnya salah, salah satu exception library standar yang bisa kamu tangkap, jadi kamu mendapat kegagalan yang jelas, bukan kerusakan data:

Aturan praktisnya: pakai [] di loop yang ketat saat kamu sudah memastikan indeksnya valid, dan at() di batas-batas tempat input yang salah bisa menyelinap masuk.

Perulangan pada vector

Cara paling rapi untuk menelusuri vector adalah range-based for loop. Ambil elemen sebagai const auto& untuk membaca tanpa menyalin, atau auto& untuk mengubahnya di tempat:

Kalau kamu memang butuh indeksnya (misalnya untuk membandingkan elemen yang bersebelahan), pakai loop penghitung klasik. Tapi perhatikan bahwa size() mengembalikan tipe unsigned (size_t). Membandingkan int i yang signed dengannya bisa memicu peringatan compiler dan perputaran nilai yang mengejutkan, jadi pilih size_t i atau loop berbasis range kalau bisa:

for (size_t i = 0; i < v.size(); i++) {   // size_t, not int
    cout << v[i];
}

size, capacity, dan reserve

Vector menyimpan dua angka: size() (berapa elemen yang dimilikinya) dan capacity() (berapa banyak yang bisa ditampungnya sebelum harus membesar). Saat sebuah push_back melebihi kapasitas, vector mengalokasikan blok yang lebih besar, menyalin setiap elemen ke sana, dan membebaskan blok lama. Itulah sebabnya push_back berulang kali murah secara rata-rata (amortized), tapi setiap realokasi tidak gratis:

Kalau kamu tahu kira-kira berapa banyak elemen yang akan ditambahkan, panggil reserve() lebih dulu untuk menghindari realokasi berulang. Perhatikan bahwa reserve() mengubah kapasitas, bukan ukuran: vector tetap punya nol elemen sampai kamu menambahkannya.

Realokasi ini juga sumber bug vector yang paling parah. Karena membesar berarti memindahkan tempat penyimpanan, setiap pointer, reference, atau iterator yang kamu simpan ke dalam vector menjadi dangling setelah push_back yang memicu realokasi:

vector<int> v = {1, 2, 3};
int& first = v[0];     // reference into the vector
v.push_back(4);        // may reallocate...
cout << first;         // DANGLING - may point at freed memory

Hal yang sama berlaku untuk iterator: jangan melakukan push_back atau erase saat sedang melakukan iterasi dengan iterator yang disimpan. Kalau kamu harus menghapus item sambil melakukan perulangan, pakai nilai kembalian erase, atau pola erase-remove dengan std::remove.

Berikutnya: map

vector sempurna saat kamu mencari sesuatu berdasarkan posisi: elemen 0, elemen 1, dan seterusnya. Tapi sering kali kamu ingin mencari berdasarkan key: nama pengguna, ID produk, sebuah kata. Untuk itulah std::map ada. Berikutnya kita akan membahas map, container key-value milik C++, termasuk cara menambah, mencari, dan menelusuri entri, serta jebakan [] yang membuat nilai default dan menjebak hampir semua orang.

Pertanyaan yang sering diajukan

Apa itu vector di C++?

std::vector adalah array dinamis (ukurannya bisa berubah) dari C++ Standard Library. Berbeda dengan array biasa, ia tahu ukurannya sendiri, otomatis membesar saat kamu menambah elemen dengan push_back, dan membebaskan memorinya untukmu. Sertakan <vector> lalu tulis vector<int> v; untuk membuatnya.

Apa perbedaan [] dan at() pada vector C++?

v[i] tidak mengecek batas sama sekali: indeks di luar rentang adalah undefined behavior (crash atau kerusakan data diam-diam). v.at(i) mengecek indeksnya dan melempar std::out_of_range kalau tidak valid. Pakai [] di loop yang performanya kritis saat indeksnya sudah divalidasi, dan at() saat kamu ingin kegagalan yang aman dan mudah di-debug.

Apakah push_back membuat pointer dan reference ke vector C++ tidak valid?

Ya, bisa. Saat kapasitas vector habis, push_back mengalokasikan ulang tempat penyimpanannya ke blok baru, dan itu membuat setiap pointer, reference, dan iterator ke elemen lama menjadi tidak valid. Jangan menyimpan reference ke sebuah elemen melewati push_back, dan panggil reserve() di awal kalau bisa, untuk menghindari realokasi yang mengejutkan.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai