C++ 中的异常处理机制是一种用于处理运行时错误的强大工具。它允许程序在遇到错误或异常情况时,能够有序地转移控制到适当的异常处理代码,并从错误中恢复。C++ 的异常处理使用了三个主要的关键字:try
、catch
和 throw
。
throw
: 当问题出现时,程序会抛出一个异常。这是通过使用 throw
关键字来完成的。
try
: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch
块。
catch
: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch
关键字用于捕获异常,可以用多个catch进行捕获
基本语法
throw:当程序遇到无法处理的情况或错误时,可以使用 throw
抛出一个异常。这告诉程序的其他部分发生了一些意外情况,通常需要特别处理。
- 在函数的 后面接
throw
(类型),列出这个函数可能抛掷的所有异常类型。 - 函数的后面接
throw()
,表示函数不抛异常。 - 若无异常接口声明,则此函数可以抛掷任何类型的异常
// 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void fun() throw(A,B,C,D);// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);// 这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw();// C++11 中新增的noexcept,表示不会抛异常
thread() noexcept;
thread (thread&& x) noexcept;
try:用于定义一个代码块,希望在其中捕获异常。任何可能抛出异常的代码应该放在 try
块中。
try { // 可能会抛出异常的代码
}
catch:与 try
配对的,用于捕获和处理特定类型的异常。当 try
块内抛出异常时,控制转移到 catch
块。
catch (const ExceptionType &e) { // 处理异常的代码
}
汇总
异常发生第一现场,抛出异常
void function( ){//... ...throw 表达式;//... ...
}
在需要关注异常的地方,捕捉异常
try{//程序function(); 把function至于try中//程序
}catch(异常类型声明){ 比如只写一个int//... 异常处理代码 ...
}catch(异常类型 形参){ 形参将会取得抛出的值//... 异常处理代码 ...
}catch(...){ 抛出的其它异常类型,可以接收任意类型//
}
如果没有catch(...),并且没有catch子句与抛出的异常类型匹配,程序会直接中断报错。
try和trow的不同
功能和目的
-
try
:try
块用于定义一个代码块,该代码块包含在执行过程中可能抛出异常的代码。- 它的目的是捕获和处理异常,以便在发生错误时使程序能够继续运行而不崩溃。
-
throw
:throw
用于实际抛出异常。它的作用是表示在程序中发生了错误,并将控制权转移到相关的异常处理程序(即catch
块)。- 它的目的是传递异常状态以及与该异常相关的信息。
控制流
-
try
:- 当程序遇到
try
块中的代码时,它会继续执行该块中的代码,直到抛出异常或代码顺利结束。 - 如果在
try
块内抛出异常,控制权立即转移到对应的catch
块,而不会继续执行try
块中抛出异常后面的代码。
- 当程序遇到
-
throw
:- 当
throw
被执行时,当前代码的执行将立即停止,并且程序的控制流转移到最近的匹配的catch
块。 throw
会引发堆栈展开,执行必要的析构函数,以安全地清理资源。
- 当
异常的产生与处理
-
try
:try
块内的代码是执行的地方,所有潜在的异常都会在这里被监视。
-
throw
:- 使用
throw
语句放置在代码中一旦发现错误或不期望的情况,即可以生成(抛出)一个异常。
- 使用
try
是用于捕获异常的代码块,定义了可能出现异常的代码范围。
throw
是用于抛出异常的语句,表示在该位置发生了错误。
异常抛出和捕获原则
1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
2. 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象, 所
以会生成一个拷贝对象,这个拷贝的临时对象会在被 catch 以后销毁。(这里的处理类似 于函数
的传值返回),续C++11之后按右值处理,调用移动构造。
double Division(int x, int y)
{// 当y == 0时抛出异常if (y == 0)throw "Division by zero condition!";elsereturn ((double)x / (double)y);
}......
try
{Division(1, 0);
}
// 类型不匹配不会激活 catch,往下执行
catch (const int* p)
{cout << p << endl;
}catch (const char* str)
{cout << str << endl;
}
异常处理的工作原理
-
异常抛出:throw关键字则用于在程序中显式地抛出异常,通知上层调用者当前代码遇到了无法继续执行的情况,当
throw
语句被执行时,程序的控制从当前的执行点转移到匹配的catch
块。 -
堆栈展开:在控制转移的过程中,C++ 会执行堆栈展开,即析构当前作用域内的所有对象,以释放资源。这使得在异常情况下,尽量避免资源泄漏。
-
异常匹配:C++ 查找与抛出的异常类型匹配的
catch
块,找到后执行该块中的代码。如果没有找到匹配的catch
块,程序将终止并可能产生未捕获异常的错误。