sambil melihat beberapa kode yang saya temukan:
throw /*-->*/new std::exception ("//...
dan saya selalu berpikir bahwa Anda tidak perlu / Anda tidak boleh menggunakan di new
sini.
Bagaimana cara yang benar, keduanya OK, jika demikian apakah ada perbedaan?
BTW dari apa yang bisa saya lihat saat "grepping" dengan PowerShell boost libs tidak pernah digunakan throw new
.
PS juga saya temukan beberapa kode CLI yang digunakan throw gcnew
. Apakah itu oke?
throw gcnew
akan berguna misalnya. jika Anda ingin kode terkelola menangkap pengecualian Anda. Bisakah seseorang mengoreksi saya tentang itu?System::Exception
umumnya mengacu pada objek yang dikelola di heap yang dikumpulkan sampah. Saya selalu dilempargcnew
dan tertangkapSystem::Exception ^
. Tentu saja saya menggunakanfinally
sepanjang waktu di C ++ / CLI juga, meskipun tidak sering mencampur dengan pengecualian C ++ ditry
blok yang sama , saya tidak yakin mengapa.Jawaban:
Cara konvensional untuk melempar dan menangkap pengecualian adalah dengan melempar objek pengecualian dan menangkapnya dengan referensi (biasanya
const
referensi). Bahasa C ++ memerlukan kompilator untuk menghasilkan kode yang sesuai untuk membangun objek pengecualian dan membersihkannya dengan benar pada waktu yang tepat.Melempar pointer ke objek yang dialokasikan secara dinamis bukanlah ide yang bagus. Pengecualian seharusnya memungkinkan Anda menulis kode yang lebih kuat saat menghadapi kondisi kesalahan. Jika Anda melempar objek pengecualian dengan cara konvensional, Anda dapat yakin bahwa objek tersebut ditangkap oleh klausa catch yang menamai tipe yang benar, oleh a
catch (...)
, apakah objek tersebut kemudian dilempar kembali atau tidak, objek tersebut akan dihancurkan dengan benar pada waktu yang tepat. (Satu-satunya pengecualian adalah jika tidak pernah tertangkap sama sekali tetapi ini adalah situasi yang tidak dapat dipulihkan, bagaimanapun cara Anda melihatnya.)Jika Anda melempar pointer ke objek yang dialokasikan secara dinamis, Anda harus memastikan bahwa apa pun tampilan stack panggilan pada titik yang Anda inginkan untuk menampilkan pengecualian, ada blok catch yang menamai tipe pointer yang benar dan memiliki
delete
panggilan yang sesuai . Exception Anda tidak boleh ditangkap olehcatch (...)
kecuali blok itu melempar kembali pengecualian yang kemudian ditangkap oleh blok penangkap lain yang menangani pengecualian dengan benar.Secara efektif, ini berarti Anda telah menggunakan fitur penanganan pengecualian yang akan mempermudah penulisan kode yang kuat dan membuatnya sangat sulit untuk menulis kode yang benar dalam semua situasi. Ini mengesampingkan masalah bahwa hampir tidak mungkin bertindak sebagai kode pustaka untuk kode klien yang tidak mengharapkan fitur ini.
sumber
Tidak perlu digunakan
new
saat melempar pengecualian.Tulis saja:
dan tangkap sebagai:
Perhatikan bahwa
yourexception
harus berasal daristd::exception
secara langsung atau tidak langsung.sumber
new
? mengapa berasalyourexception
daristd::exception
?throw std::exception;
berhasil? g ++ tampaknya tidak akan mengkompilasinya ...std::exception
adalah tipe, dan Anda tidak bisa melempar tipe , Anda sudah melempar objek . Jadi sintaksnya harus seperti ini:throw std::exception();
Itu akan dikompilasi. Sekarang betapa bagusnya itu, adalah pertanyaan yang sama sekali berbeda.Melempar
new std::exception
benar jika situs panggilan mengharapkan untuk menangkapstd::exception*
. Tapi tidak ada yang akan mengharapkan untuk menangkap pointer ke sebuah pengecualian. Bahkan jika Anda mendokumentasikan itulah yang dilakukan fungsi Anda dan orang-orang membaca dokumentasinya, mereka masih cenderung lupa dan mencoba menangkap referensi ke suatustd::exception
objek.sumber
new std::exception
hanya benar jika situs panggilan mengharapkan untuk menangkap pointer DAN mengharapkan untuk mengambil alih pengelolaan pengecualian alokasi DAN tidak akan pernah ada kasus di mana fungsi Anda akan dipanggil oleh sesuatu yang tidak secara eksplisit menangkap pointer yang benar (catch(...)
atau tidak ada penanganan sama sekali) jika tidak maka akan ada kebocoran objek. Singkatnya, ini dapat diperkirakan sebagai "tidak pernah".FAQ C ++ memiliki diskusi yang bagus tentang ini:
Pada dasarnya "kecuali ada alasan bagus untuk tidak melakukannya, tangkap dengan referensi. Hindari menangkap dengan nilai, karena itu menyebabkan salinan dibuat dan salinan dapat memiliki perilaku yang berbeda dari apa yang dilemparkan. Hanya dalam keadaan yang sangat khusus Anda dapat menangkap dengan pointer. "
sumber
A
berbeda dari jenisnyaA*
jadi jika saya melakukannyathrow A()
saya TIDAK bisa menangkapnyacatch(A* e)
karena jenisnya sama sekali berbeda.Operator baru tidak dapat menjamin bahwa itu tidak akan pernah menimbulkan pengecualian. Karena alasan ini, menggunakannya untuk menampilkan pengecualian "valid" (dimaksudkan) akan menghasilkan kode yang tidak dijamin tidak akan mogok. Karena mungkin hanya ada satu pengecualian pada satu waktu, dan program Anda mencoba membuang dua pengecualian sebelum salah satu dari mereka dapat ditangkap, hal terbaik yang dapat dilakukan implementasi adalah segera membatalkan program Anda, misalnya dengan memanggil std :: terminate.
sumber