Bagikan melalui


Masa pakai objek dan manajemen sumber daya (RAII)

Tidak seperti bahasa terkelola, C++ tidak memiliki pengumpulan sampah otomatis, proses internal yang merilis memori tumpukan dan sumber daya lain saat program berjalan. Program C++ bertanggung jawab untuk mengembalikan semua sumber daya yang diperoleh ke sistem operasi. Kegagalan untuk merilis sumber daya yang tidak digunakan disebut kebocoran. Sumber daya yang bocor tidak tersedia untuk program lain sampai proses keluar. Kebocoran memori khususnya adalah penyebab umum bug dalam pemrograman gaya C.

C++ modern menghindari penggunaan memori tumpukan sebanyak mungkin dengan mendeklarasikan objek pada tumpukan. Ketika sumber daya terlalu besar untuk tumpukan, sumber daya harus dimiliki oleh objek. Saat objek diinisialisasi, objek memperoleh sumber daya yang dimilikinya. Objek tersebut kemudian bertanggung jawab untuk melepaskan sumber daya dalam destruktornya. Objek pemilik itu sendiri dideklarasikan pada tumpukan. Prinsip bahwa objek sumber daya sendiri juga dikenal sebagai "akuisisi sumber daya adalah inisialisasi," atau RAII.

Ketika objek tumpukan pemilik sumber daya keluar dari cakupan, destruktornya secara otomatis dipanggil. Dengan cara ini, pengumpulan sampah di C++ terkait erat dengan masa pakai objek, dan deterministik. Sumber daya selalu dirilis pada titik yang diketahui dalam program, yang dapat Anda kontrol. Hanya deterministik deterministik seperti yang ada di C++ yang dapat menangani memori dan sumber daya non-memori secara merata.

Contoh berikut menunjukkan objek wsederhana . Ini dinyatakan pada tumpukan pada cakupan fungsi, dan dihancurkan di akhir blok fungsi. Objek w tidak memiliki sumber daya (seperti memori yang dialokasikan timbunan). Satu-satunya anggotanya g sendiri dideklarasikan pada tumpukan, dan hanya keluar dari cakupan bersama dengan w. Tidak ada kode khusus yang diperlukan dalam widget destruktor.

class widget {
private:
    gadget g;   // lifetime automatically tied to enclosing object
public:
    void draw();
};

void functionUsingWidget () {
    widget w;   // lifetime automatically tied to enclosing scope
                // constructs w, including the w.g gadget member
    // ...
    w.draw();
    // ...
} // automatic destruction and deallocation for w and w.g
  // automatic exception safety,
  // as if "finally { w.dispose(); w.g.dispose(); }"

Dalam contoh berikut, w memiliki sumber daya memori dan harus memiliki kode dalam destruktornya untuk menghapus memori.

class widget
{
private:
    int* data;
public:
    widget(const int size) { data = new int[size]; } // acquire
    ~widget() { delete[] data; } // release
    void do_something() {}
};

void functionUsingWidget() {
    widget w(1000000);  // lifetime automatically tied to enclosing scope
                        // constructs w, including the w.data member
    w.do_something();

} // automatic destruction and deallocation for w and w.data

Karena C++11, ada cara yang lebih baik untuk menulis contoh sebelumnya: dengan menggunakan penunjuk cerdas dari pustaka standar. Penunjuk cerdas menangani alokasi dan penghapusan memori yang dimilikinya. Menggunakan pointer pintar menghilangkan kebutuhan akan destruktor eksplisit di widget kelas.

#include <memory>
class widget
{
private:
    std::unique_ptr<int[]> data;
public:
    widget(const int size) { data = std::make_unique<int[]>(size); }
    void do_something() {}
};

void functionUsingWidget() {
    widget w(1000000);  // lifetime automatically tied to enclosing scope
                        // constructs w, including the w.data gadget member
    // ...
    w.do_something();
    // ...
} // automatic destruction and deallocation for w and w.data

Dengan menggunakan pointer pintar untuk alokasi memori, Anda dapat menghilangkan potensi kebocoran memori. Model ini berfungsi untuk sumber daya lain, seperti handel file atau soket. Anda dapat mengelola sumber daya Anda sendiri dengan cara yang sama di kelas Anda. Untuk informasi selengkapnya, lihat Penunjuk cerdas.

Desain C++ memastikan objek dihancurkan ketika mereka keluar dari cakupan. Artinya, mereka dihancurkan karena blok keluar, dalam urutan konstruksi terbalik. Ketika objek dihancurkan, basis dan anggotanya dihancurkan dalam urutan tertentu. Objek yang dideklarasikan di luar blok mana pun, pada cakupan global, dapat menyebabkan masalah. Mungkin sulit untuk men-debug, jika konstruktor objek global melemparkan pengecualian.

Baca juga

Selamat datang kembali di C++
Referensi bahasa C++
Pustaka Standar C++