C++:noexcept关键字

本文介绍了C++11中noexcept关键字在处理移动语义异常中的作用,以及如何使用它来提高代码效率和避免潜在风险。还讨论了noexcept与throw的关系和其在不同版本C++中的变化。
摘要由CSDN通过智能技术生成

C++11之前我们可以使用throw抛出异常,但是随着C++11中移动语义的产生,throw不能很好的解决移动语义过程中的异常处理,不同于拷贝,移动的过程如果出错的话不能保证原来的数据是否受到影响,为此C++11引入了noexcept关键字来处理这个问题。

noexcept作为说明符
函数使用noexcept声明时,会告诉编译器这个函数不会发生异常,进而让编译器使用效率更高的检测代码,如果真的发生异常时程序会调用terminate函数直接结束程序。
noexcept还可以接收一个bool类型的参数,该参数必须是一个常量表达式用以决定函数是否可以抛出异常,默认是true

//不带参数
void fun()noexcept{}
//带参数
template <class T>
T fun()noexcept(std::is_fundamental<T>::value){}

noexcept作为运算符
作为运算符接收表达式参数返回bool类型,判断表达式是否可以抛出异常

void fun()noexcept{}
void fun(int){}
void fun(char)throw(){}
int main(){
	std::cout<<noexcept(fun())
	<<noexcept(fun(1))
	<<noexcept(fun('a'))<<std::endl;
}
//分别返回 true false true

解决移动语义的风险

  • 遇到风险直接编译报错
template<class T>
void swap(T& a,T& b)
noexcept(noexcept(T(std::move(a))))&&
noexcept(noexcept(T(std::move(b))))
{
	static_assert(noexcept(T(std::move(a)))&&
		noexcept(T(std::move(b))));
	T tmp(std::move(a));
	a=std::move(b);
	b=std::move(tmp);
}
  • 遇到风险改用拷贝
template<class T>
void swap_impl(T& a,T& b,std::integral_constant<bool,true>)noexcept{
	T tmp(std::move(a));
	a=std::move(b);
	b=std::move(tmp);
}
template<class T>
void swap_impl(T& a,T& b,std::integral_constant<bool,false>){
	T tmp(a);
	a=b;
	b=tmp;
}
template<class T>
void swap(T& a,T& b)
noexcept(noexcept(swap_impl(a,b
	std::integral_constant<bool,noexcept(T(std::move(a)))&&
	noexcept(a.operator=(std::move(b)))>())))
{
	swap_impl(a,b,
	std::integral_constant<bool,noexcept(T(std::move(a)))&&
	noexcept(a.operator=(std::move(b)))>());
}

noexcept和throw()

  • C++11:声明函数的结果相同,noexcept更高效
  • C++17:throw变为noexcept的别名
  • C++20:废除throw

默认声明noexcept的函数

  • 默认构造函数
  • 默认拷贝构造
  • 默认移动构造
  • 默认赋值函数
  • 默认移动赋值函数
  • 析构函数
  • delete运算符函数

使用noexcept的情景:

  1. 绝对不会发生错误的函数
  2. 绝对不能发生错误的函数

C++17之前noexcept并不作为函数类型的一部分,下列代码中foo并不具备noexcept声明为fp赋值后fp会失去noexcept的声明效果

void(*fp)()noexcept=nullptr;
void foo(){}
int main(){
	fp=&foo;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值