Sebaliknya, Anda harus selalu lebih memilih alokasi tumpukan, sejauh sebagai aturan praktis, Anda tidak boleh memiliki new / delete dalam kode pengguna Anda.
Seperti yang Anda katakan, saat variabel dideklarasikan di stack, destruktornya secara otomatis dipanggil saat berada di luar cakupan, yang merupakan alat utama Anda untuk melacak masa pakai resource dan menghindari kebocoran.
Jadi secara umum, setiap kali Anda perlu mengalokasikan sumber daya, apakah itu memori (dengan memanggil baru), pegangan file, soket atau apa pun, bungkus dalam kelas di mana konstruktor memperoleh sumber daya, dan destruktor melepaskannya. Kemudian Anda dapat membuat objek jenis itu di tumpukan, dan Anda dijamin bahwa sumber daya Anda dibebaskan saat berada di luar ruang lingkup. Dengan cara itu Anda tidak perlu melacak pasangan baru / hapus Anda di mana-mana untuk memastikan Anda menghindari kebocoran memori.
Nama paling umum untuk idiom ini adalah RAII
Lihat juga kelas penunjuk cerdas yang digunakan untuk membungkus hasil penunjuk pada kasus yang jarang terjadi saat Anda harus mengalokasikan sesuatu dengan yang baru di luar objek RAII khusus. Sebagai gantinya, Anda meneruskan penunjuk ke penunjuk cerdas, yang kemudian melacak masa pakainya, misalnya dengan penghitungan referensi, dan memanggil destruktor saat referensi terakhir keluar dari ruang lingkup. Pustaka standar memiliki std::unique_ptr
manajemen berbasis ruang lingkup sederhana, dan std::shared_ptr
yang menghitung referensi untuk mengimplementasikan kepemilikan bersama.
Banyak tutorial yang mendemonstrasikan pembuatan instance objek menggunakan cuplikan seperti ...
Jadi apa yang Anda temukan adalah bahwa kebanyakan tutorial payah. ;) Sebagian besar tutorial mengajari Anda praktik C ++ yang buruk, termasuk memanggil baru / hapus untuk membuat variabel bila tidak diperlukan, dan memberi Anda kesulitan melacak seumur hidup alokasi Anda.
Meskipun memiliki banyak hal di tumpukan mungkin merupakan keuntungan dalam hal alokasi dan pembebasan otomatis, ini memiliki beberapa kelemahan.
Anda mungkin tidak ingin mengalokasikan objek yang besar di Stack.
Pengiriman dinamis! Pertimbangkan kode ini:
Ini akan mencetak "B". Sekarang mari kita lihat apa yang terjadi saat menggunakan Stack:
Ini akan mencetak "A", yang mungkin tidak intuitif bagi mereka yang terbiasa dengan Java atau bahasa berorientasi objek lainnya. Alasannya adalah Anda tidak memiliki penunjuk ke sebuah instance
B
lagi. Sebagai gantinya, sebuah instanceB
dibuat dan disalin kea
variabel tipeA
.Beberapa hal mungkin terjadi tanpa disadari, terutama saat Anda baru mengenal C ++. Di C Anda memiliki petunjuk dan hanya itu. Anda tahu bagaimana menggunakannya dan mereka SELALU melakukannya. Dalam C ++ tidak demikian. Bayangkan saja apa yang terjadi, ketika Anda menggunakan a dalam contoh ini sebagai argumen untuk sebuah metode - segalanya menjadi lebih rumit dan itu TIDAK membuat perbedaan besar jika
a
bertipeA
atauA*
atau bahkanA&
(panggilan-oleh-referensi). Banyak kombinasi yang mungkin dan semuanya berperilaku berbeda.sumber
Nah, alasan untuk menggunakan pointer akan persis sama dengan alasan menggunakan pointer di C yang dialokasikan dengan malloc: jika Anda ingin objek Anda hidup lebih lama dari variabel Anda!
Bahkan sangat disarankan untuk TIDAK menggunakan operator baru jika Anda dapat menghindarinya. Apalagi jika Anda menggunakan pengecualian. Secara umum, jauh lebih aman membiarkan kompiler membebaskan objek Anda.
sumber
Saya telah melihat anti-pola ini dari orang-orang yang tidak memahami operator & alamat. Jika mereka perlu memanggil fungsi dengan pointer, mereka akan selalu mengalokasikan di heap sehingga mereka mendapatkan pointer.
sumber
Perlakukan heap sebagai real estat yang sangat penting dan gunakan dengan sangat bijaksana. Aturan dasar yang umum adalah menggunakan tumpukan jika memungkinkan dan menggunakan heap jika tidak ada cara lain. Dengan mengalokasikan objek pada stack Anda bisa mendapatkan banyak keuntungan seperti:
(1). Anda tidak perlu khawatir tentang pelepasan tumpukan jika ada pengecualian
(2). Anda tidak perlu khawatir tentang fragmentasi memori yang disebabkan oleh alokasi lebih banyak ruang daripada yang diperlukan oleh pengelola heap Anda.
sumber
Satu-satunya alasan yang saya khawatirkan adalah Dog sekarang ditempatkan di stack, bukan di heap. Jadi, jika Dog berukuran megabyte, Anda mungkin mengalami masalah,
Jika Anda memang perlu pergi ke rute baru / hapus, berhati-hatilah dengan pengecualian. Dan karena itu, Anda harus menggunakan auto_ptr atau salah satu jenis penunjuk cerdas penunjuk untuk mengelola masa pakai objek.
sumber
Tidak ada alasan untuk baru (di heap) ketika Anda dapat mengalokasikan di tumpukan (kecuali karena alasan tertentu Anda memiliki tumpukan kecil dan ingin menggunakan tumpukan.
Anda mungkin ingin mempertimbangkan untuk menggunakan shared_ptr (atau salah satu variasinya) dari pustaka standar jika Anda ingin mengalokasikan di heap. Itu akan menangani melakukan penghapusan untuk Anda setelah semua referensi ke shared_ptr sudah tidak ada lagi.
sumber
Ada alasan tambahan, yang tidak disebutkan orang lain, mengapa Anda mungkin memilih untuk membuat objek Anda secara dinamis. Objek dinamis berbasis heap memungkinkan Anda memanfaatkan polimorfisme .
sumber
Saya memiliki masalah yang sama di Visual Studio. Anda harus menggunakan:
KelasAnda-> classMethod ();
daripada:
yourClass.classMethod ();
sumber