c++中的noexcept 关键字

1.

在许多代码中代码当中我们都能看到有关键字noexcept。比如std::initializer_list的默认构造函数,其中使用了noexcept。
该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化。如果在运行时,noexecpt函数向外抛出了异常(如果函数内部捕捉了异常并完成处理,这种情况不算抛出异常),程序会直接终止,调用std::terminate()函数,该函数内部会调用std::abort()终止程序。
使用noexcept表明函数或操作不会发生异常,会给编译器更大的优化空间。然而,并不是加上noexcept就能提高效率,以下情形鼓励使用noexcept:
移动构造函数(move constructor)
移动分配函数(move assignment)
noexcept 是为了替代 throw() 而提出的一个新的关键字,在C++ 中使用函数异常声明列表来查看函数可能抛出的异常。比如:

void test() throw (int,float);

上例就是一个函数异常声明列表,该声明指出 test 可能抛出int和 float 类型的异常。但是在实际编程中很少使用这种写法,所以这一特性在 C++11 中被抛弃。另外,如果异常声明列表写成如下形式:

void test() throw();

这种写法表示函数 test 不抛出任何异常,而这种写法在 c++11 中被新的关键字 noexcept 异常声明所取代。noexcept 修饰符有两种形式,第一种就只是在函数声明后加上 noexcept 关键字。如下:

void test() noecept;

另外一种形式则是接受一个常量表达式(参阅《常量表达式》)作为参数,如下所示:

void test() noexcept(常量表达式);

常量表达式的结果会被转换成一个 bool 类型的值,该值为 true,表示函数不会抛出异常,反之则可能抛出异常。而不带常量表达式的 noexcept,相当于声明了 noexcept(true),即不会抛出异常。下面用例子来演示:

#include <iostream>
using namespace std;
void Throw()
{
	throw 1;
}

void NoBlockThrow()
{ 
	Throw(); 
}

void BlockThrow()noexcept
{ 
	Throw(); 
}

int main(void){
	try {
		Throw();
	}
	catch(...) {
		cout << "Found throw."	<< endl; // Found throw
	}

	try {
		NoBlockThrow();
	}
	catch(...) {
		cout << "Throw is not blocked" <<endl;
	}
	
	try {
		BlockThrow();
	}
	catch(...) {
		cout << "Found throw1" << endl;
	}
	return 0;
}

输出:

vtlk:mutex$./demo 
Found throw.
Throw is not blocked
terminate called after throwing an instance of 'int'
已放弃 (核心已转储)

我们定义了Throw函数,该函数的唯一作用是抛出一个异常。而NoBlockThrow是一个调用Throw的普通函数,BlockThrow则是一个noexcept修饰的函数。从main的运行中我们可以看到,NoBlockThrow会让Throw函数抛出的异常继续抛出,直到main中的catch语句将其捕捉。而BlockThrow则会直接调用std::terminate中断程序的执行,从而阻止了异常的继续传播。从使用效果上看,这与C++98中的throw()是一样的。

noexcept作为一个操作符时,通常可以用于模板。比如:

template <class T> 
  void fun() noexcept(noexcept(T())) {}

这里,fun函数是否是一个noexcept的函数,将由T()表达式是否会抛出异常所决定。这里的第二个noexcept就是一个noexcept操作符。当其参数是一个有可能抛出异常的表达式的时候,其返回值为false,反之为true
noexcept修饰的函数通过std::terminate的调用来结束程序的执行的方式可能无法保证对象的析构函数的正常调用,无法保证栈的自动释放等noexcept更大的作用是保证应用程序的安全。比如一个类析构函数不应该抛出异常,那么对于常被析构函数调用的delete函数来说,C++11默认将delete函数设置成noexcept,就可以提高应用程序的安全性;C++11让类的析构函数默认也是noexcept(true)的。当然,如果程序员显式地为析构函数指定了noexcept,或者类的基类或成员有noexcept(false)的析构函数,析构函数就不会再保持默认值

#include <iostream> 
using namespace std;  
 
class A {  
public:
		~A() { throw 1; }  
};  
 
class B {
public:
    ~B() noexcept(false) { throw 2; }  
};  
 
class C {  
public:
	B b;  
};  
 
int funA() { A a; }  
int funB() { B b; }  
int funC() { C c; }  
 
int main() {  
    try {  
        funB();  
    }  
    catch(...){  
        cout << "caught funB." << endl; // caught funB.  
    }  
 
    try {  
        funC();  
    }  
    catch(...){  
        cout << "caught funC." << endl; // caught funC.  
    }  
 
    try {  
        funA(); // terminate called after throwing an instance of 'int'  
    }  
    catch(...){  
        cout << "caught funA." << endl;  
    }  
}  

输出:

vtlk:mutex$./demo1
caught funB.
caught funC.
terminate called after throwing an instance of 'int'
已放弃 (核心已转储)

上面的代码中析构函数声明为noexcept(false)的类B,还是包含了B类型成员的类C,其析构函数都是可以抛出异常的。只有什么都没有声明的类A,其析构函数被默认为noexcept(true),从而阻止了异常的扩散

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
noexcept关键字C++11引入的,用于指明某个函数不会抛出异常。在函数声明或定义时使用noexcept关键字可以明确表示该函数不会抛出任何异常。noexcept关键字有两种形式,一种是直接在函数声明后加上noexcept关键字,例如"void test() noexcept;",另一种是使用noexcept作为操作符,通常用于模板。例如"template <class T> void fun() noexcept(noexcept(T())) {}"。 使用noexcept关键字可以提供更好的代码可读性和性能优化。在函数声明或定义使用noexcept关键字可以帮助程序员更加清晰地了解函数的异常安全性,并在编译时进行一些优化。当一个函数被声明为noexcept时,编译器可以在编译时对其进行一些优化,提高代码的执行效率。 需要注意的是,noexcept并不会禁止函数抛出异常,而是用来明确表示函数不会抛出异常。如果一个被声明为noexcept的函数在运行时抛出异常,程序将会终止。因此,在使用noexcept关键字时要确保函数的实现没有抛出异常的可能性。 总之,noexcept关键字C++11引入的用于指明某个函数不会抛出异常的关键字,可以提高代码的可读性和性能优化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [c++的noexcept 关键字](https://blog.csdn.net/weixin_68294039/article/details/127023089)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [C++ vector扩容解析noexcept应用场景](https://download.csdn.net/download/weixin_38514805/13707167)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值