Pertama, saya sangat menyadari mengapa tidak ada konstruksi 'akhirnya' dalam C ++? tetapi diskusi komentar yang panjang tentang pertanyaan lain tampaknya membutuhkan pertanyaan terpisah.
Terlepas dari masalah bahwa finally
dalam C # dan Java pada dasarnya hanya dapat ada satu kali (== 1) per cakupan dan satu cakupan dapat memiliki beberapa (== n) C + + destructors, saya pikir mereka pada dasarnya adalah hal yang sama. (Dengan beberapa perbedaan teknis.)
Namun, pengguna lain berpendapat :
... Saya mencoba untuk mengatakan bahwa dtor pada dasarnya adalah alat untuk (Release sematics) dan akhirnya secara inheren merupakan alat untuk (Commant semantic). Jika Anda tidak melihat alasannya: pertimbangkan mengapa melegalkan satu sama lain di blok akhirnya sah, dan mengapa hal yang sama tidak untuk destruktor. (Dalam beberapa hal, ini data vs kontrol. Destructor adalah untuk melepaskan data, akhirnya untuk melepaskan kontrol. Mereka berbeda; sangat disayangkan bahwa C ++ mengikat mereka bersama-sama.)
Bisakah seseorang membersihkan ini?
sumber
A
danB
. Jika satu utas dilempar,A's
transaksi penggulungan kembali tidak boleh menghancurkan sumber daya yang dialokasikanB
, misalnya - status utas tidak tergantung satu sama lain, dan memori yang terus-menerus hidup di tumpukan tidak tergantung pada keduanya. Namun, biasanya di C ++, memori tumpukan masih terikat ke objek di tumpukan.std::vector
objek mungkin hidup di stack tetapi menunjuk ke memori di heap - baik objek vektor (di stack) dan isinya (di heap) akan dibatalkan alokasi selama stack bersantai dalam kasus itu, karena menghancurkan vektor pada stack akan memanggil destructor yang membebaskan memori terkait pada heap (dan juga menghancurkan elemen heap itu). Biasanya untuk keamanan pengecualian, sebagian besar objek C ++ hidup di stack, bahkan jika mereka hanya menangani menunjuk ke memori di heap, mengotomatiskan proses membebaskan kedua heap dan memori stack di stack, bersantai.Senang Anda memposting ini sebagai pertanyaan. :)
Saya mencoba mengatakan bahwa destructor dan
finally
secara konseptual berbeda:finally
adalah untuk kembali ke penelepon ( kontrol )Pertimbangkan, katakanlah, pseudo-code hipotetis ini:
finally
di sini adalah menyelesaikan masalah kontrol sepenuhnya dan bukan masalah manajemen sumber daya.Tidak masuk akal untuk melakukan itu di destructor karena berbagai alasan:
logfile.print
gagal, sedangkan kehancuran (secara konseptual) tidak bisa gagalBerikut contoh lain, kali ini seperti di Javascript:
Dalam contoh di atas, sekali lagi, tidak ada sumber daya yang akan dirilis.
Bahkan,
finally
blok memperoleh sumber daya secara internal untuk mencapai tujuannya, yang berpotensi gagal. Oleh karena itu, tidak masuk akal untuk menggunakan destruktor (jika Javascript memilikinya).Di sisi lain, dalam contoh ini:
finally
sedang menghancurkan sumber dayab
,. Ini masalah data. Masalahnya bukan tentang mengembalikan kontrol ke pemanggil, tetapi tentang menghindari kebocoran sumber daya.Kegagalan bukanlah suatu pilihan, dan seharusnya (secara konseptual) tidak pernah terjadi.
Setiap rilis
b
harus dipasangkan dengan akuisisi, dan masuk akal untuk menggunakan RAII.Dengan kata lain, hanya karena Anda dapat menggunakan salah satu untuk mensimulasikan baik itu tidak berarti keduanya adalah satu dan masalah yang sama atau bahwa keduanya adalah solusi yang tepat untuk kedua masalah.
sumber
finally
sebagian besar digunakan untuk melepaskan faktor sumber daya (non-memori) ke dalam ini?finally
.finally
klausa. Pandangan dunia C ++ akan memperkenalkan kelas yang mengelola “sumber daya” tugas ini ke variabel pseudo-global. Pengertian konseptual apa itu? Tetapi destruktor adalah palu C ++ untuk eksekusi kode akhir blok yang diperlukan.Jawaban k3b benar-benar mengucapkannya dengan baik:
Adapun "sumber daya", saya suka merujuk ke Jon Kalb: RAII harus berarti Tanggung Jawab Akuisisi adalah Inisialisasi .
Bagaimanapun, seperti untuk implisit vs eksplisit ini tampaknya benar-benar itu:
Saya pikir itu saja untuk bagian konseptual, ...
... sekarang ada IMHO beberapa detail menarik:
fault
blok untuk menjalankan kode yang hanya harus dijalankan jika ada scope-exit yang luar biasa.SCOPE_EXIT
,SCOPE_FAIL
danSCOPE_SUCCESS
di perpustakaan kebodohan . Lihat Andrei Alexandrescu: Penanganan Kesalahan dalam C ++ / Declarative Control Flow (diadakan di NDC 2014 )Saya juga tidak berpikir bahwa c'tor / d'tor perlu secara konseptual "memperoleh" atau "membuat" apa pun, terlepas dari tanggung jawab untuk menjalankan beberapa kode dalam destruktor. Yang akhirnya juga: menjalankan beberapa kode.
Dan sementara kode pada akhirnya blok tentu saja dapat mengeluarkan pengecualian, itu tidak cukup perbedaan bagi saya untuk mengatakan bahwa mereka secara konseptual berbeda di atas eksplisit vs implisit.
(Plus, saya tidak yakin sama sekali bahwa kode "baik" harus dibuang dari akhirnya - mungkin itu pertanyaan lain untuk dirinya sendiri.)
sumber
observer
contoh Anda bahwa melempar akan ada ide yang sangat buruk.) Jangan ragu untuk membuka obrolan, jika Anda ingin membahas ini lebih lanjut. Pasti menyenangkan memikirkan argumen Anda. Bersulang.