Saya melihat di C ++ ada beberapa cara untuk mengalokasikan dan membebaskan data dan saya mengerti bahwa ketika Anda menelepon malloc
Anda harus menelepon free
dan ketika Anda menggunakan new
operator Anda harus memasangkan dengan delete
dan itu adalah kesalahan untuk mencampur keduanya (misalnya Memanggil free()
sesuatu yang telah dibuat dengan new
operator), tapi saya tidak jelas kapan saya harus menggunakan malloc
/ free
dan kapan saya harus menggunakan new
/ delete
dalam program dunia nyata saya.
Jika Anda seorang pakar C ++, beri tahu saya aturan apa pun yang Anda ikuti dalam hal ini.
c++
memory-management
malloc
new-operator
JVApen
sumber
sumber
Jawaban:
Kecuali Anda dipaksa untuk menggunakan C, Anda seharusnya tidak pernah menggunakan
malloc
. Selalu gunakannew
.Jika Anda membutuhkan banyak data, lakukan saja seperti:
Hati-hati meskipun ini tidak benar:
Alih-alih, Anda harus melakukan ini saat menghapus array data:
Itu
new
kunci adalah cara C ++ untuk melakukannya, dan itu akan memastikan bahwa tipe Anda akan memanggil konstruktornya . Katanew
kunci juga lebih aman-tipe sedangkanmalloc
tidak-aman sama sekali.Satu-satunya cara saya bisa berpikir itu akan bermanfaat untuk digunakan
malloc
adalah jika Anda perlu mengubah ukuran buffer data Anda. Katanew
kunci tidak memiliki cara analog sepertirealloc
. Therealloc
Fungsi mungkin bisa memperpanjang ukuran sepotong memori untuk Anda lebih efisien.Perlu disebutkan bahwa Anda tidak dapat mencampur
new
/free
danmalloc
/delete
.Catatan: Beberapa jawaban dalam pertanyaan ini tidak valid.
sumber
new[]
akan jauh lebih aman daripadastd::vector
? Jika seseorang menggunakannew[]
, satu-satunya cara penunjuk akan menjadi tidak valid adalah melalui eksplisitdelete
, sedangkan memori yang dialokasikan untuk suatustd::vector
dapat batal ketika vektor diubah ukurannya atau meninggalkan ruang lingkup. (Perhatikan bahwa ketika menggunakannew[]
salah satu harus memungkinkan untuk kemungkinan bahwa seseorang mungkin tidak dapat memanggildelete
jika metode async masih tertunda; jika mungkin perlu untuk meninggalkan operasi async, orang mungkin harus mengatur untuk menghapus melalui callback) .Jawaban singkatnya adalah: jangan gunakan
malloc
untuk C ++ tanpa alasan yang bagus untuk melakukannya.malloc
memiliki sejumlah kekurangan saat digunakan dengan C ++, yangnew
didefinisikan untuk diatasi.Kekurangan diperbaiki oleh baru untuk kode C ++
malloc
bukan typesafe dengan cara apa pun yang berarti. Di C ++ Anda diminta untuk mengembalikan darivoid*
. Ini berpotensi menimbulkan banyak masalah:Ini lebih buruk dari itu. Jika jenis yang dimaksud adalah POD (data lama biasa) maka Anda dapat menggunakan secara semi-bijaksana
malloc
untuk mengalokasikan memori untuknya, sepertif2
halnya dalam contoh pertama.Namun tidak begitu jelas apakah suatu tipe POD. Fakta bahwa dimungkinkan untuk tipe tertentu untuk berubah dari POD ke non-POD tanpa menghasilkan kesalahan kompiler dan berpotensi sangat sulit untuk men-debug masalah adalah faktor yang signifikan. Sebagai contoh jika seseorang (mungkin programmer lain, selama pemeliharaan, jauh kemudian adalah untuk membuat perubahan yang menyebabkan
foo
tidak lagi menjadi POD maka tidak ada kesalahan yang jelas akan muncul pada waktu kompilasi seperti yang Anda harapkan, misalnya:akan membuat
malloc
darif2
juga menjadi buruk, tanpa diagnosa yang jelas. Contoh di sini sepele, tetapi mungkin untuk secara tidak sengaja memperkenalkan non-PODness lebih jauh (misalnya dalam kelas dasar, dengan menambahkan anggota non-POD). Jika Anda memiliki C ++ 11 / boost, Anda dapat menggunakanis_pod
untuk memeriksa bahwa asumsi ini benar dan menghasilkan kesalahan jika tidak:Meskipun dorongan tidak dapat menentukan apakah suatu tipe POD tanpa C ++ 11 atau ekstensi kompiler lainnya.
malloc
kembaliNULL
jika alokasi gagal.new
akan melemparstd::bad_alloc
. Perilaku nanti menggunakanNULL
pointer tidak ditentukan. Pengecualian memiliki semantik bersih saat dilempar dan dilempar dari sumber kesalahan. Membungkusmalloc
dengan tes yang sesuai pada setiap panggilan tampaknya membosankan dan rawan kesalahan. (Anda hanya perlu lupa sekali untuk membatalkan semua pekerjaan bagus itu). Pengecualian dapat diizinkan untuk menyebar ke tingkat di mana penelepon dapat memprosesnya dengan masuk akal, di manaNULL
jauh lebih sulit untuk lulus kembali secara bermakna. Kami dapat memperluassafe_foo_malloc
fungsi kami untuk melempar pengecualian atau keluar dari program atau memanggil beberapa penangan:Pada dasarnya
malloc
adalah fitur C dannew
merupakan fitur C ++. Akibatnyamalloc
tidak bermain bagus dengan konstruktor, itu hanya terlihat mengalokasikan sejumlah byte. Kami dapat memperluassafe_foo_malloc
lebih lanjut untuk menggunakan penempatannew
:safe_foo_malloc
Fungsi kami tidak terlalu umum - idealnya kami menginginkan sesuatu yang dapat menangani semua jenis, bukan hanyafoo
. Kita dapat mencapai ini dengan templat dan templat variadic untuk konstruktor non-default:Namun sekarang dalam memperbaiki semua masalah yang kami identifikasi sejauh ini, kami praktis telah menemukan kembali
new
operator default . Jika Anda akan menggunakanmalloc
dan penempatannew
maka Anda mungkin juga hanyanew
perlu mulai dengan!sumber
struct
danclass
pada dasarnya berarti hal yang sama; Saya ingin tahu apakah akan ada masalah denganstruct
dicadangkan untuk POD dan mungkin semuaclass
jenis dianggap non-POD. Setiap tipe yang didefinisikan oleh kode yang mendahului penemuan C ++ akan menjadi POD, jadi saya tidak akan berpikir kompatibilitas ke belakang akan menjadi masalah di sana. Apakah ada keuntungan memiliki jenis non-POD yang dinyatakan sebagaistruct
bukanclass
?struct
danclass
melakukan hal yang hampir sama adalah keputusan desain yang luar biasa yang sekarang memungkinkan fitur rapi yang disebut "metaclasses" (dari Herb) .$class
. Saya tidak yakin apa yang harus dilakukan denganclass
danstruct
menjadi sinonim.class
danstruct
mengartikan hal yang sama secara efektif, Anda dapat melakukan transformasi sewenang-wenang terhadap mereka ($class
) tanpa khawatir membuatclass
astruct
dan sebaliknya.Dari C ++ FQA Lite :
Maaf, saya tidak bisa menolak. :)
sumber
Selalu gunakan yang baru di C ++. Jika Anda membutuhkan blok memori yang tidak diketik, Anda dapat menggunakan operator baru secara langsung:
sumber
operator new
adalahoperator delete
. Ini bukan tindakan yang didefinisikan dengan baik untuk memanggildelete
ekspresi dengan tipevoid*
.Gunakan
malloc
dan hanya untuk mengalokasikan memori yang akan dikelola oleh perpustakaan c-centric dan API. Gunakan dan (dan variannya) untuk semua yang Anda kontrol.free
new
delete
[]
sumber
malloc
. Demikian juga jika fungsi sepertistrdup
perlu membuat objek dan mengembalikannya ke pemanggil, sangat masuk akal untuk menentukan bahwa pemanggil harus memanggilfree
objek ketika tidak lagi diperlukan. Bagaimana bisa fungsi-fungsi tersebut menghindari mengekspos penggunaan malloc / gratis untuk pemanggil?malloc
dalam C ++?baru vs malloc ()
1)
new
adalah operator yang , sementaramalloc()
adalah fungsi .2)
new
memanggil konstruktor , sementaramalloc()
tidak.3)
new
mengembalikan tipe data yang tepat , sementaramalloc()
mengembalikan batal * .4)
new
tidak pernah mengembalikan NULL (akan gagal) sementaramalloc()
mengembalikan NULL5) Realokasi memori tidak ditangani oleh
new
selagimalloc()
bisasumber
char* ptr = new (std::nothrow) char [323232];
new
fungsirealloc
daripadamalloc
, dan mulai dengan variabel pointer Anda dijalankan untukNULL
. Jika Anda ingin sepotong memori resizable di C ++, di sisi lain, saya akan menyarankanstd::vector
sebagai kebalikan darirealloc
... Itu atau file.Untuk menjawab pertanyaan Anda, Anda harus tahu perbedaan antara
malloc
dannew
. Perbedaannya sederhana:malloc
mengalokasikan memori , sementaranew
mengalokasikan memori DAN memanggil konstruktor dari objek Anda mengalokasikan memori untuk.Jadi, kecuali Anda dibatasi untuk C, Anda tidak boleh menggunakan malloc, terutama ketika berhadapan dengan objek C ++. Itu akan menjadi resep untuk merusak program Anda.
Juga perbedaan antara
free
dandelete
cukup sama. Perbedaannya adalah bahwadelete
akan memanggil destruktor objek Anda selain membebaskan memori.sumber
Ada satu perbedaan besar antara
malloc
dannew
.malloc
mengalokasikan memori. Ini bagus untuk C, karena di C, benjolan memori adalah objek.Di C ++, jika Anda tidak berurusan dengan tipe POD (yang mirip dengan tipe C) Anda harus memanggil konstruktor pada lokasi memori untuk benar-benar memiliki objek di sana. Jenis non-POD sangat umum di C ++, karena banyak fitur C ++ membuat objek secara otomatis non-POD.
new
mengalokasikan memori dan membuat objek di lokasi memori itu. Untuk jenis non-POD ini berarti memanggil konstruktor.Jika Anda melakukan sesuatu seperti ini:
Pointer yang Anda peroleh tidak dapat direferensikan karena tidak menunjuk ke objek. Anda harus memanggil konstruktor sebelum dapat menggunakannya (dan ini dilakukan dengan menggunakan penempatan
new
).Sebaliknya, jika Anda melakukannya:
Anda mendapatkan pointer yang selalu valid, karena
new
membuat objek.Bahkan untuk tipe POD, ada perbedaan yang signifikan antara keduanya:
Sepotong kode ini akan mencetak nilai yang tidak ditentukan, karena objek POD yang dibuat oleh
malloc
tidak diinisialisasi.Dengan
new
, Anda bisa menentukan konstruktor yang akan dipanggil, dan dengan demikian mendapatkan nilai yang terdefinisi dengan baik.Jika Anda benar-benar menginginkannya, Anda dapat menggunakan gunakan
new
untuk mendapatkan objek POD yang tidak diinisialisasi. Lihat jawaban lain ini untuk informasi lebih lanjut tentang itu.Perbedaan lainnya adalah perilaku pada kegagalan. Ketika gagal mengalokasikan memori,
malloc
mengembalikan pointer nol, sementaranew
melempar pengecualian.Yang pertama mengharuskan Anda untuk menguji setiap pointer yang dikembalikan sebelum menggunakannya, sementara yang berikutnya akan selalu menghasilkan pointer yang valid.
Untuk alasan ini, dalam kode C ++ Anda harus menggunakan
new
, dan tidakmalloc
. Tetapi meskipun demikian, Anda tidak boleh menggunakannew
"di tempat terbuka", karena ia memperoleh sumber daya yang perlu Anda rilis nanti. Ketika Anda menggunakan,new
Anda harus segera menyerahkan hasilnya ke kelas pengelola sumber daya:sumber
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:
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:
C ++ 17 juga menambahkan
std::optional
yang dapat mencegah Anda dari membutuhkan alokasi memoriSegera setelah 'instans' keluar dari ruang lingkup, memori dibersihkan. Mentransfer kepemilikan juga mudah:
Jadi kapan Anda masih membutuhkannya
new
? Hampir tidak pernah dari C ++ 11 on. Sebagian besar yang Anda gunakanstd::make_unique
sampai Anda mencapai titik di mana Anda menekan API yang mentransfer kepemilikan melalui pointer mentah.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:
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.
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:
sumber
Ada beberapa hal yang
new
tidak yangmalloc
tidak:new
membangun objek dengan memanggil konstruktor objek itunew
tidak memerlukan typecasting memori yang dialokasikan.Jadi, jika Anda menggunakan
malloc
, maka Anda perlu melakukan hal-hal di atas secara eksplisit, yang tidak selalu praktis. Selain itu,new
bisa kelebihan beban tetapimalloc
tidak bisa.sumber
Jika Anda bekerja dengan data yang tidak memerlukan konstruksi / penghancuran dan membutuhkan realokasi (mis., Array int yang besar), maka saya percaya malloc / free adalah pilihan yang baik karena memberi Anda realall, yang jauh lebih cepat daripada memcpy baru -delete (ada di kotak Linux saya, tapi saya kira ini mungkin tergantung platform). Jika Anda bekerja dengan objek C ++ yang bukan POD dan membutuhkan konstruksi / penghancuran, maka Anda harus menggunakan operator baru dan menghapus.
Lagi pula, saya tidak mengerti mengapa Anda tidak harus menggunakan keduanya (asalkan Anda membebaskan memori malloced Anda dan menghapus objek yang dialokasikan dengan yang baru) jika dapat mengambil keuntungan dari peningkatan kecepatan (kadang-kadang yang signifikan, jika Anda realokasi array besar POD) yang realall dapat berikan kepada Anda.
Kecuali Anda membutuhkannya, Anda harus tetap menggunakan / menghapus yang baru di C ++.
sumber
Jika Anda memiliki kode C yang ingin Anda portingkan ke C ++, Anda dapat meninggalkan panggilan malloc () di dalamnya. Untuk kode C ++ baru, saya sarankan menggunakan yang baru.
sumber
Jika Anda menggunakan C ++, coba gunakan baru / hapus alih-alih malloc / calloc karena mereka adalah operator. Untuk malloc / calloc, Anda perlu memasukkan header lain. Jangan mencampur dua bahasa berbeda dalam kode yang sama. Pekerjaan mereka serupa dalam segala hal, keduanya mengalokasikan memori secara dinamis dari segmen heap di tabel hash.
sumber
new
akan menginisialisasi nilai default struct dan dengan benar menghubungkan referensi ke dalamnya.Misalnya
Jadi
new struct test_s
akan mengembalikan struktur yang diinisialisasi dengan referensi yang berfungsi, sedangkan versi malloc'ed tidak memiliki nilai default dan referensi intern tidak diinisialisasi.sumber
Dari perspektif yang lebih rendah, baru akan menginisialisasi semua memori sebelum memberikan memori sedangkan malloc akan menyimpan konten asli memori.
sumber
Dalam skenario berikut, kami tidak dapat menggunakan yang baru karena memanggil konstruktor.
sumber
The
new
dandelete
operator dapat beroperasi pada kelas dan struktur, sedangkanmalloc
danfree
hanya bekerja dengan blok memori yang perlu menjadi pemain.Menggunakan
new/delete
akan membantu meningkatkan kode Anda karena Anda tidak perlu membuang memori yang dialokasikan ke struktur data yang diperlukan.sumber
Rare case untuk dipertimbangkan menggunakan malloc / free daripada new / delete adalah ketika Anda mengalokasikan dan kemudian realokasi (tipe pod sederhana, bukan objek) menggunakan realloc karena tidak ada fungsi yang mirip dengan realall di C ++ (meskipun ini dapat dilakukan dengan menggunakan lebih banyak pendekatan C ++).
sumber
malloc () digunakan untuk secara dinamis menetapkan memori dalam C sementara pekerjaan yang sama dilakukan oleh new () dalam c ++. Jadi, Anda tidak dapat mencampur konvensi pengkodean 2 bahasa. Akan lebih baik jika Anda meminta perbedaan antara calloc dan malloc ()
sumber
malloc
C ++.