c++异常处理机制和noexcept关键字

文章介绍了C++中的异常处理机制,包括函数内和函数外的异常捕获形式,两者的异同在于异常处理后的程序执行流程和局部变量释放。函数内捕获允许函数继续执行,而函数外捕获会导致函数终止。同时,文章讨论了异常未处理的情况以及noexcept特性,该特性用于标记不抛出异常的函数,如果函数内部抛出异常,程序将立即终止。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简述

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(...){ // 并不能捕获到异常,程序异常终止
		// 异常处理
	}
}

说明

文章给出的部分内容为个人理解,可能存在纰漏。如有错误,希望指出。会及时更正,避免误导他人。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值