简述
C++ 中的异常处理机制可以用来在程序出现错误或异常情况时进行处理。一个异常是由抛出操作发起的,然后被一个或多个 try 块捕获和处理。
异常处理形式
try {
// 可能会抛出异常的代码
} catch (exceptionType1 e) {
// 处理 exceptionType1 类型的异常
} catch (exceptionType2 e) {
// 处理 exceptionType2 类型的异常
}
// ...
两种异常捕获形式
函数内捕获
发生异常的函数内部存在对异常得到捕获和处理(try-catch)能力。
void func ()
{
// do something
try {
throw std::exception(); // 代码产生异常
}
catch (...) { // 捕获异常
// 异常处理
}
}
函数外捕获
发生异常的函数没能力处理函数内部发生的异常,异常抛出到此函数的调用者,让上层函数取处理异常。
void func ()
{
// do something
throw std::exception(); // 代码产生异常
}
void test()
{
try{
func(); // 抛出异常
}
catch(...){
// 异常处理
}
}
两种方式的异同
异
函数内捕获:异常捕获处理后,函数能继续执行。从try-catch语句后继续执行。
函数外捕获:异常处理后,发送异常的函数终止运行,但不影响外层函数的运行。
同
- 都能对异常进行处理
- 都能释放异常函数中定义的栈变量(局部变量)。
#include <iostream>
using namespace std;
struct Sample
{
Sample() : val(0){ std::cout << "Sample\n"; }
Sample(int _val) : val(_val){ std::cout << val << " Sample\n"; }
~Sample() { std::cout << val << " ~Sample\n";}
int val;
};
void func ()
{
Sample sam(23);
Sample* sam1 = new Sample(666);
try {
throw std::exception();
}
catch (...) {
cout << "Catched one exception in function" << endl;
delete sam1;
}
puts("异常处理后结束,函数继续执行 --- ");
}
void err_func()
{
Sample sam(23);
Sample* sam1 = new Sample(666);
delete sam1; // 提前手动释放堆上的变量
throw std::exception();
}
void handle_err()
{
try {
err_func();
}
catch (...) {
cout << "Catched one exception out of function" << endl;
}
}
int main()
{
func();
puts("----------------------------------");
handle_err();
return 0;
}
/*output
23 Sample
666 Sample
Catched one exception in function
666 ~Sample
异常处理后结束,函数继续执行 ---
23 ~Sample
----------------------------------
23 Sample
666 Sample
666 ~Sample
23 ~Sample
Catched one exception out of function
*/
异常发生后变量的释放
异常得到处理
定义在栈中局部变量,异常处理后会自动释放
使用new关键字,在堆中创建的变量,需手动调用delete进行释放内存。
注意:如果函数抛出异常向让函数调用者处理,那么必须先把函数中new出的内存释放后,再抛出异常,否则内存泄漏。
异常未处理
程序异常终止,变量不会自动释放。
#include <iostream>
using namespace std;
struct Sample
{
Sample() : val(0){ std::cout << "Sample\n"; }
Sample(int _val) : val(_val){ std::cout << val << " Sample\n"; }
~Sample() { std::cout << val << " ~Sample\n";}
int val;
};
void danger_func()
{
Sample sam(23);
throw std::exception();
}
int main()
{
danger_func();
return 0;
}
/*output
23 Sample
terminate called after throwing an instance of 'std::exception'
what(): std::exception
*/
noexcept
特性说明
c++11特性。
noexcept 表明当前函数不往函数外抛出异常(或理解为即使抛出异常,也会被忽略,不能被捕获。)。
即使函数能产生异常,在当前函数即被捕获和处理。如果产生异常且在当前函数不能处理,立即调用std::terminate进行程序终止(即使此函数的调用者存在对此异常的捕获也不可)。
使用形式
void func() noexcept { // do something }
或者
void func1() noexcept(true) { // do something }
void func2() noexcept(bool型表达式) { // do something }
// noexcept(true) 等价于 noexcept
注意
使用函数外捕获去试图捕获并处理一个被noexcept修饰的函数(不向外抛出异常的函数),是没有意义的。
void func () noexcept
{
// do something
throw std::exception(); // 代码产生异常
}
void test()
{
try{
func();
}
catch(...){ // 并不能捕获到异常,程序异常终止
// 异常处理
}
}
说明
文章给出的部分内容为个人理解,可能存在纰漏。如有错误,希望指出。会及时更正,避免误导他人。