c++11 noexcept关键字作用

c++11 noexcept关键字作用

c++2.0中,一条经典的规范是:尽可能地为一个函数加上noexcept声明,意味着程序员向编译器保证该函数不会发射异常。

这条规范说的很对。那么,本文我们主要来探讨:

  • 为什么给函数加上noexcept会优化其性能?
  • noexcept的常见用法?
  • 你可能会觉得自己也不确定这个函数是否会在运行时发射异常,那么到底什么时机应该为函数加上noexcept可以获得最佳优化?

一、noexcept声明对函数性能的优化

这个原因从直观上理解应该是:既然开发者确保此函数不会发射异常,那么编译器也就没有必要为处理这个”可能“发生的异常添加一些事先预备好的目标代码,这在一定程度上减少了函数编译后生成的目标代码。

二、 noexcept的常见用法及注意事项

c++11和c++98对阻止异常抛出的写法不一样:

void func()throw(){}//c++98,这种写法并不能完全享受到上面提到的那种优化
void func()noexcept{}//c++11

在c++11中,noexcept的用法如下:

void func()noexcept{}//1. 
void func()noexcept(express){}//2. 

第二种写法将根据表达式的真假来决断函数是否发射异常,noexcept等价于noexcept(true)。

需要注意的是,如果承诺了func函数是不会抛出异常的,那么必须保证func调用的其他函数也是不会抛出异常的,否则无法保证func的noexcept性质。因此,我们可以百分百确定一个函数不会发射异常的情况是比较少见的!需要了解的是,c++11为所有类的析构函数都加上了“隐式”noexcept声明。

另外,假设我们承诺的noexcept函数在运行时真的发射了异常会怎么样呢?(一定要注意,如果使用了catch子句捕获并处理了异常,那不算发射异常!)我在GNU下测试过,运行时还是会抛出异常然后程序崩溃。只是在编译生成目标代码时做了优化而已。

void func()noexcept{
    int* a=nullptr;
    *a=2;//抛出一个异常 
}

bash输出:

zkcc@LAPTOP-OHBI7I8S:~/mytest$ g++ test_cast.cc -o test_cast && ./test_cast
Segmentation fault

三、为函数加上noexcept声明的最佳时机

直接给出建议:当你为一个类设计移动系列函数时,如果可以,最应该为其加上noexcept,以便此类在使用标准库容器时可以用移动操作来代替拷贝。

咋回事呢?移动操作加上noexcept与标准库容器的移动优化有啥关系呢?

以vector为例,很多标准库容器需要特定时机的扩容操作:把元素从旧内存拷贝到新开辟的内存,再析构旧内存中的元素。

针对这种情况明显可以用移动操作来优化之。(为什么移动操作比拷贝操作速度更快,什么时候会有明显的优化?这个问题我们之后也会讨论!)

但标准库的做法是:如果容器中类的移动操作函数带有noexcept声明,则使用移动操作来代替拷贝;如果没有noexcept声明,则用拷贝来完成扩容。

因此你会发现,将各种移动系列的函数设计为noexcept,会对标准库性能提升有巨大的帮助!

  • 16
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值