解析C++中的 noexcept
一. 概述
noexcept 是C++11中的特性,既是一个说明符,也是一个运算符。能够说明函数是否会抛出异常,如下:
1 struct X { 2 3 int f() const noexcept { 4 return 58; 5 } 6 7 void g() noexcept {} 8 }; 9 10 int foo() noexcept { 11 return 42; 12 }
noexcept指示上述的几个函数不会抛出异常,编译器可以优化代码。
如果有异常抛出,则会调用std::terminate结束生命周期。
二. 带参数的noexcept
带参数的noexcept作用为:如果noexcept(true),则不会抛出异常,反之则可能有异常,下面的例子中,可以用noexcept检查传入模板参数是不是基础类型。
1 template <class T> 2 T copy(const T& o) noexcept(std::is_fundamental<T>::value) { 3 ... 4 }
这个函数可以优化为:
1 template <class T> 2 T copy(const T& o) noexcept(noexcept (T(o))) { 3 4 }
这里用了2个noexcept,第二个判断T(o)是否可能抛出异常,第一个接受第二个的返回值,决定T类型复制函数是否声明为不抛出异常
三. noexcept使用场景
1. 解决移动构造和移动赋值的问题
下例用noexcept实现一个移动语义的容器经常用到的工具函数swap。如果move没有抛出异常的可能,那么函数进行移动操作,否则进行复制操作。
1 template <class T> 2 void swap(T &a, T &b) 3 noexcept(noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b)))) { 4 static_assert (noexcept (T(std::move(a))) && noexcept (a.operator=(std::move(b))) ); 5 T temp(std::move(a)); 6 a = std::move(b); 7 b = std::move(temp); 8 }
2. 用于析构函数。在新版本的编译器中,析构函数是默认加上关键字noexcept的。
3. 叶子函数。叶子函数是指在函数内部不分配栈空间,也不调用其它函数,也不存储非易失性寄存器,也不处理异常。
四. 注意事项
1. 在新版本编译器中,默认构造函数,默认复制构造函数,默认赋值函数,默认移动构造函数,默认移动赋值函数均自带noexcept,但使用者自定义或重载的上述函数需要手动加上noexcept才有此功能。
2. c++11中保留了throw(), 实现和noexcept类似的功能,区别是throw()不会针对编译器进行优化,但是C++20中移除了throw()。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具