Spesifikasi pengecualian (throw, noexcept) (C++)
Spesifikasi pengecualian adalah fitur bahasa C++ yang menunjukkan niat programmer tentang jenis pengecualian yang dapat disebarluaskan oleh fungsi. Anda dapat menentukan bahwa fungsi mungkin atau mungkin tidak keluar dengan pengecualian dengan menggunakan spesifikasi pengecualian. Pengkompilasi dapat menggunakan informasi ini untuk mengoptimalkan panggilan ke fungsi, dan untuk mengakhiri program jika pengecualian yang tidak terduga lolos dari fungsi.
Sebelum C++17 ada dua jenis spesifikasi pengecualian. Spesifikasi noexcept baru di C++11. Ini menentukan apakah kumpulan pengecualian potensial yang dapat lolos dari fungsi kosong. Spesifikasi pengecualian dinamis, atau throw(optional_type_list)
spesifikasi, tidak digunakan lagi di C++11 dan dihapus di C++17, kecuali untuk throw()
, yang merupakan alias untuk noexcept(true)
. Spesifikasi pengecualian ini dirancang untuk memberikan informasi ringkasan tentang pengecualian apa yang dapat dibuang dari fungsi, tetapi dalam praktiknya ditemukan bermasalah. Satu spesifikasi pengecualian dinamis yang terbukti agak berguna adalah spesifikasi yang tidak bersyarat throw()
. Misalnya, deklarasi fungsi:
void MyFunction(int i) throw();
memberi tahu pengkompilasi bahwa fungsi tidak melemparkan pengecualian apa pun. Namun, dalam /std:c++14
mode ini dapat menyebabkan perilaku yang tidak ditentukan jika fungsi melemparkan pengecualian. Oleh karena itu, sebaiknya gunakan noexcept
operator alih-alih operator di atas:
void MyFunction(int i) noexcept;
Tabel berikut ini meringkas implementasi Microsoft C++ dari spesifikasi pengecualian:
Spesifikasi pengecualian | Makna |
---|---|
noexcept noexcept(true) throw() |
Fungsi ini tidak melemparkan pengecualian. Dalam /std:c++14 mode (yang merupakan default), noexcept dan noexcept(true) setara. Ketika pengecualian dilemparkan dari fungsi yang dinyatakan noexcept atau noexcept(true) , std::terminate dipanggil. Ketika pengecualian dilemparkan dari fungsi yang dinyatakan sebagai throw() dalam /std:c++14 mode, hasilnya adalah perilaku yang tidak ditentukan. Tidak ada fungsi khusus yang dipanggil. Ini adalah divergensi dari standar C++14, yang mengharuskan pengkompilasi untuk memanggil std::unexpected . Visual Studio 2017 versi 15.5 dan yang lebih baru: Dalam /std:c++17 mode , , noexcept noexcept(true) , dan throw() semuanya setara. Dalam /std:c++17 mode, throw() adalah alias untuk noexcept(true) . Dalam /std:c++17 mode dan yang lebih baru, ketika pengecualian dilemparkan dari fungsi yang dideklarasikan dengan salah satu spesifikasi ini, std::terminate dipanggil sebagaimana diperlukan oleh standar C++17. |
noexcept(false) throw(...) Tidak ada spesifikasi |
Fungsi ini dapat melemparkan pengecualian dari jenis apa pun. |
throw(type) |
(C++14 dan yang lebih lama) Fungsi dapat melemparkan pengecualian jenis type . Pengkompilasi menerima sintaks, tetapi menafsirkannya sebagai noexcept(false) . Dalam /std:c++17 mode dan yang lebih baru, kompilator mengeluarkan peringatan C5040. |
Jika penanganan pengecualian digunakan dalam aplikasi, harus ada fungsi dalam tumpukan panggilan yang menangani pengecualian yang dilemparkan sebelum keluar dari cakupan luar fungsi yang ditandai noexcept
, , noexcept(true)
atau throw()
. Jika ada fungsi yang dipanggil antara fungsi yang melempar pengecualian dan yang menangani pengecualian ditentukan sebagai noexcept
, (atau throw()
dalam mode), program dihentikan /std:c++17
ketika fungsi noexcept noexcept(true)
menyebarkan pengecualian.
Perilaku pengecualian fungsi tergantung pada faktor-faktor berikut:
Mode kompilasi standar bahasa mana yang diatur.
Apakah Anda mengkompilasi fungsi di bawah C atau C++.
Opsi pengkompilasi mana yang
/EH
Anda gunakan.Apakah Anda secara eksplisit menentukan spesifikasi pengecualian.
Spesifikasi pengecualian eksplisit tidak diizinkan pada fungsi C. Fungsi C diasumsikan untuk tidak melemparkan pengecualian di bawah /EHsc
, dan dapat melemparkan pengecualian terstruktur di bawah /EHs
, , /EHa
atau /EHac
.
Tabel berikut ini meringkas apakah fungsi C++ mungkin berpotensi dilemparkan di bawah berbagai opsi penanganan pengecualian kompilator:
Function | /EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
Fungsi C++ tanpa spesifikasi pengecualian | Ya | Ya | Ya | Ya |
Fungsi C++ dengan noexcept spesifikasi pengecualian , noexcept(true) , atau throw() |
Tidak | No | Ya | Ya |
Fungsi C++ dengan noexcept(false) spesifikasi pengecualian , throw(...) , atau throw(type) |
Ya | Ya | Ya | Ya |
Contoh
// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>
void handler() {
printf_s("in handler\n");
}
void f1(void) throw(int) {
printf_s("About to throw 1\n");
if (1)
throw 1;
}
void f5(void) throw() {
try {
f1();
}
catch(...) {
handler();
}
}
// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
// f1();
// }
void __declspec(nothrow) f2(void) {
try {
f1();
}
catch(int) {
handler();
}
}
// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
f1();
}
int main() {
f2();
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
f5();
}
About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler
Baca juga
try
, throw
, dan catch
Pernyataan (C++)
Praktik terbaik C++ modern untuk pengecualian dan penanganan kesalahan
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk