Dua wilayah memori pada Chapter sebelumnya punya pasangan konseptual yang sama pentingnya: storage duration, yaitu aturan yang menentukan kapan sebuah objek diciptakan dan kapan ia berakhir. Standar C++ membaginya menjadi tiga macam utama: automatic storage yang hidup bersama blok kodenya, static storage yang hidup sepanjang program berjalan, dan dynamic storage yang hidup sampai kita melepaskannya sendiri. Memahami perbedaan ketiganya menjelaskan banyak perilaku yang tampak aneh bagi pemula — misalnya mengapa nilai variabel lokal tidak bisa dipakai setelah bloknya selesai, padahal alamatnya masih terkenang. Chapter ini membuktikan ketiganya dengan satu program yang melacak kehidupan setiap objek.
Automatic Storage: Hidup Bersama Bloknya #
Objek dengan automatic storage duration diciptakan pada saat definisinya dieksekusi dan dibongkar secara otomatis ketika blok tempat ia berada selesai. Inilah kategori hampir semua variabel lokal yang selama ini kita tulis — termasuk parameter function. Jika ada beberapa objek dalam satu blok, pembongkarannya berlangsung dalam urutan terbalik: yang dideklarasikan terakhir, berakhir lebih dulu. Kepastian urutan ini membuat compiler bisa menjamin kebersihan stack, dan membuat kita bebas dari pekerjaan pelepasan manual.
Static Storage: Hidup Sepanjang Program #
Objek dengan static storage duration berada di wilayah data program, bukan di stack, dan hidup dari sebelum main() dimulai sampai program selesai. Kategori ini mencakup variabel global dan variabel ber-static — keduanya sudah kita kenal sisi visibility-nya pada Chapter Scope dan Lifetime Variabel; kali ini fokusnya pada sisi umurnya. Catatan pentingnya: lifetime panjang bukan berarti boleh lalai, karena objek statis menempati memori sejak awal sampai akhir program entah dipakai atau tidak.
Membuktikan Tiga Urutan Kehidupan #
Program berikut mendeklarasikan satu objek statis, satu objek otomatis, dan — sebagai jembatan — menyinggung dynamic storage yang dibahas penuh pada Chapter new dan delete. Kelas Pelacak mencetak pesan di constructor dan destructor, sehingga kita bisa membaca urutan kehidupannya langsung dari output.
#include <iostream>
#include <string>
class Pelacak {
public:
explicit Pelacak(const std::string& nama) : nama_(nama) {
std::cout << nama_ << " diciptakan\n";
}
~Pelacak() {
std::cout << nama_ << " dibebaskan\n";
}
private:
std::string nama_;
};
Pelacak statis("storage-statis"); // static storage: hidup sepanjang program
int main() {
std::cout << "main() dimulai\n";
{
Pelacak otomatis("storage-otomatis"); // automatic storage
std::cout << "masih di dalam blok\n";
} // storage-otomatis dibebaskan TEPAT di sini
std::cout << "blok berakhir, program lanjut\n";
return 0;
} // storage-statis dibebaskan SETELAH main() selesai
Output yang Dihasilkan:
storage-statis diciptakan
main() dimulai
storage-otomatis diciptakan
masih di dalam blok
storage-otomatis dibebaskan
blok berakhir, program lanjut
storage-statis dibebaskanUrutan output di atas adalah bukti dari ketiga aturan sekaligus:
- Baris 16 (global
Pelacak statis(...)): objek statis diciptakan sebelummain()berjalan — pesannya muncul paling awal, dan dibebaskan paling akhir setelahmain()selesai. - Baris 22 (
Pelacak otomatis(...)): objek otomatis diciptakan tepat saat baris definisinya dieksekusi, di tengahmain(). - Baris 24 (
}): penutup blok menjalankan destructorotomatisseketika — inilah batas hidup automatic storage, bukan akhir program. - Baris 27 (
return 0;):main()selesai; destructor objek statis baru dijalankan setelahnya oleh runtime.
Dynamic Storage: Hidup Sampai Kita Lepas #
Kategori ketiga, dynamic storage duration, tidak terikat blok dan tidak terikat main(): objeknya diciptakan lewat operator new dan hanya berakhir ketika operator delete dipanggil. Sisa program ini — sampai Section ini selesai — hampir sepenuhnya membahas kategori inilah, karena kebebasannya menyimpan risiko yang paling besar: kalau delete tidak pernah dipanggil, memorinya bocor sampai program berhenti.
| Storage duration | Diciptakan | Berakhir | Contoh |
|---|---|---|---|
| Automatic | Saat definisi dieksekusi | Akhir blok, urutan terbalik | Variabel lokal |
| Static | Sebelum main() (umumnya) | Setelah main() selesai | Variabel global, static |
| Dynamic | Saat new dijalankan | Saat delete dipanggil | new, smart pointer |
Tabel di atas bisa kita pakai sebagai ringkasan mental setiap kali menulis deklarasi baru. Dari ketiganya, hanya dynamic storage yang menuntut pekerjaan manual dari kita — dan itulah sebabnya chapter berikutnya mendedikasikan dirinya penuh untuk operator new dan delete.
Referensi: cppreference — storage duration , cppreference — destructor .