Alokasi dinamis hanya diperlukan ketika masa hidup objek harus berbeda dari ruang lingkup yang dibuatnya (Ini berlaku juga untuk membuat ruang lingkup lebih kecil sebagai lebih besar) dan Anda memiliki alasan khusus di mana menyimpannya dengan nilai tidak kerja.
Sebagai contoh:
std::vector<int> *createVector(); // Bad
std::vector<int> createVector(); // Good
auto v = new std::vector<int>(); // Bad
auto result = calculate(/*optional output = */ v);
auto v = std::vector<int>(); // Good
auto result = calculate(/*optional output = */ &v);
Dari C ++ 11 dan seterusnya, kita harus std::unique_ptr
berurusan dengan memori yang dialokasikan, yang berisi kepemilikan memori yang dialokasikan.std::shared_ptr
dibuat ketika Anda harus berbagi kepemilikan. (Anda akan membutuhkan ini kurang dari yang Anda harapkan dalam program yang bagus)
Membuat instance menjadi sangat mudah:
auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11
C ++ 17 juga menambahkan std::optional
yang dapat mencegah Anda dari membutuhkan alokasi memori
auto optInstance = std::optional<Class>{};
if (condition)
optInstance = Class{};
Segera setelah 'instans' keluar dari ruang lingkup, memori dibersihkan. Mentransfer kepemilikan juga mudah:
auto vector = std::vector<std::unique_ptr<Interface>>{};
auto instance = std::make_unique<Class>();
vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)
Jadi kapan Anda masih membutuhkannya new
? Hampir tidak pernah dari C ++ 11 on. Sebagian besar yang Anda gunakan std::make_unique
sampai Anda mencapai titik di mana Anda menekan API yang mentransfer kepemilikan melalui pointer mentah.
auto instance = std::make_unique<Class>();
legacyFunction(instance.release()); // Ownership being transferred
auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr
Dalam C ++ 98/03, Anda harus melakukan manajemen memori manual. Jika Anda berada dalam kasus ini, cobalah memutakhirkan ke versi standar yang lebih baru. Jika Anda macet:
auto instance = new Class(); // Allocate memory
delete instance; // Deallocate
auto instances = new Class[42](); // Allocate memory
delete[] instances; // Deallocate
Pastikan Anda melacak kepemilikan dengan benar agar tidak ada kebocoran memori! Pindah semantik juga belum berfungsi.
Jadi, kapan kita perlu malloc di C ++? Satu-satunya alasan yang valid adalah untuk mengalokasikan memori dan menginisialisasi nanti melalui penempatan baru.
auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
auto instance = new(instanceBlob)Class{}; // Initialize via constructor
instance.~Class(); // Destroy via destructor
std::free(instanceBlob); // Deallocate the memory
Meskipun, di atas valid, ini dapat dilakukan melalui operator baru juga. std::vector
adalah contoh yang bagus untuk ini.
Akhirnya, kita masih memiliki gajah di dalam ruangan: C
. Jika Anda harus bekerja dengan C-library di mana memori dialokasikan dalam kode C ++ dan dibebaskan dalam kode C (atau sebaliknya), Anda dipaksa untuk menggunakan malloc / gratis.
Jika Anda berada dalam kasus ini, lupakan fungsi virtual, fungsi anggota, kelas ... Hanya struct dengan POD di dalamnya yang diizinkan.
Beberapa pengecualian terhadap aturan:
- Anda sedang menulis perpustakaan standar dengan struktur data lanjutan di mana malloc sesuai
- Anda harus mengalokasikan sejumlah besar memori (Dalam salinan memori file 10GB?)
- Anda memiliki perkakas yang mencegah Anda menggunakan konstruksi tertentu
- Anda perlu menyimpan jenis yang tidak lengkap