当前位置: 首页 > news >正文

C++之noexcept

目录

1.概述

2.noexcept作为说明符

3.noexcept作为运算符

4.传统throw与noexcept比较

5.原理剖析

6.总结


1.概述

        在C++中,noexcept是一个关键字,用于指定函数不会抛出异常。如果函数保证不会抛出异常,编译器可以进行更多优化,比如防止异常传播时的栈展开,或者生成更有效的代码。

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

        C++11后,逐渐形成“函数要么可能发射异常,要么保证不会发生异常”的共识。并提出了关键字noexcept用于指明函数保证自己不会发生异常。

        示例如下:

constexpr int myAdd(int a, int b) noexcept {return a + b;
}

        把noexcept关键字放在函数声明和定义的括号后,表示该函数不会抛出任何异常。若函数抛出异常,则程序会终止。

        如果想要允许该程序抛出异常,则可在noexcept后添加false:

constexpr int myAdd(int a, int b) noexcept (false) {return a + b;
}

        此时允许函数抛出异常。

2.noexcept作为说明符

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

void myFunction() noexcept {// 这个函数不会抛出异常
}//带参数
template <class T>
void myFunction() noexcept(std::is_class<T>::value){}

   noexcept也可以用于重载解析:

void myFunction() {// 这个函数可能会抛出异常
}void myFunction() noexcept {// 这个函数不会抛出异常
}

        noexcept既可以表征普通函数不发射异常,也可以用于表征成员函数不发射异常。

//普通函数
int add(int a, int b)noexcept
{return a+b;
}//成员函数
class People {
public:
People(std::string name, int age) :m_name{ name }, m_age{ age } {}
~People()noexcept = default;inline const int GetAge()const noexcept
{return m_age;
}inline const std::string GetName()const noexcept
{return m_name;
}private:std::string m_name{ "" };int m_age{ 0 };
};

3.noexcept作为运算符

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

void no_exception()noexcept
{throw true;
}void exception()
{throw true;
}void myfunc()
{int a=10; int b=10;exception();int c= a+b;
}int test_noexcept_oper() {std::cout<<std::boolalpha<<noexcept(no_exception())<<"\n"<<noexcept(exception())<<"\n"<<noexcept(myfunc())<<"\n";return 0;
}

移动构造函数和移动赋值运算符通常被设计为不抛出异常,因为它们只是“窃取”资源而不是复制它们。在这些函数上使用noexcept可以确保它们不会抛出异常,并允许编译器进行额外的优化。

class MyClass {  
public:  // 移动构造函数  MyClass(MyClass&& other) noexcept : /* 初始化列表 */ {  // 实现资源的移动  }  // 移动赋值运算符  MyClass& operator=(MyClass&& other) noexcept {  // 实现资源的移动  return *this;  }  
};

 解决移动语义的风险

1)遇到风险直接编译报错

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);
}

2)遇到风险改用拷贝

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,bstd::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)))>());
}

4.传统throw与noexcept比较

        在C++中,传统的throw异常机制和noexcept说明符提供了两种处理运行时错误的方法,它们在用途和目的上有明显的不同。下面是关于这两者之间比较的一些关键点:

传统的throw异常机制

  1. 错误处理throw语句用于在代码中抛出一个异常,表示发生了一个运行时错误或异常情况。这允许程序员在代码的多个位置中定义可能的错误情况,并在一个集中的错误处理位置(通常是catch块)中处理它们。

  2. 传播性:当异常被抛出时,它会沿着调用栈向上传播,直到找到一个能够处理该异常的catch块。如果没有找到合适的catch块,程序将调用std::terminate()并终止。

  3. 灵活性:异常机制允许程序员在多个不同的函数或方法之间传播错误,而不必依赖返回值或错误代码来指示错误。这使得代码更加清晰和易于维护。

  4. 性能开销:异常处理机制在运行时有一定的性能开销,因为它涉及到堆栈展开、异常表查找和可能的函数调用(对于catch块)。因此,在性能敏感的代码区域中频繁使用异常可能会导致性能下降。

noexcept说明符

  1. 异常保证noexcept说明符用于指示一个函数是否可能抛出异常。当函数被标记为noexcept时,它承诺不会抛出任何异常(除非它是由另一个noexcept(false)的函数调用引起的)。

  2. 优化机会:当编译器知道一个函数是noexcept时,它可以执行一些优化,例如消除额外的异常处理代码,从而提高程序的执行速度。

  3. 提高异常安全性:如果一个noexcept函数确实抛出了异常,程序将调用std::terminate()并终止。这有助于确保在资源转移或关键操作期间不会因异常而导致资源泄漏或其他未定义行为。

  4. 设计约束noexcept提供了一种方式来限制函数的异常行为,这在设计高性能或低延迟的系统时尤为重要。通过使用noexcept,程序员可以确保某些关键操作不会因异常而中断。

比较

  • 用途throw用于在代码中抛出异常以指示错误情况,而noexcept用于指示函数是否可能抛出异常。
  • 性能throw/catch机制在运行时有一定的性能开销,而noexcept则可以提高性能,因为它允许编译器进行额外的优化。
  • 错误处理throw/catch提供了一种灵活的错误处理机制,允许程序员在多个不同的函数或方法之间传播错误。而noexcept则更多地关注于函数的异常行为约束和性能优化。
  • 设计考虑:在设计高性能或低延迟的系统时,noexcept可能是一个重要的考虑因素,因为它可以确保关键操作不会因异常而中断。而在设计更一般性的库或应用程序时,throw/catch可能更为适用。

5.原理剖析

        noexcept保证函数不会发射异常,那么noexcept是如何保证的呢?为了分析这个问题,不妨让noexcept函数抛出异常,同时让普通函数抛出异常作为对照组,对比分析两个函数的行为。验证代码及行为如下:

//当noexcept函数触发异常时,会直接在函数内抛出异常的位置中断,异常未扩散。
//已在 xxx.exe 中执行断点指令(__debugbreak()语句或类似调用)。
void no_exception()noexcept
{throw true;
}//当常规函数触发异常时会提示异常;
//0x00007FFA2D8F543C 处(位于 xxxx.exe 中)有未经处理的异常:
// Microsoft C++ 异常: bool,位于内存位置 0x0000005B28B3F444 处。
void exception()
{throw true;
}

  由如上行为可知,noexcept函数在触发异常时直接中断,异常自然无法向外发射(传递)。

  正是由于其不向外发射异常特性,为编译器提供了更大的舞台。

  • 更大的优化空间:因为noexcept标注的函数,其异常不会向外传递,自然也就不存在开解调用栈(开解调用栈是指在异常处理、函数返回或程序终止过程中,系统自动执行的调用栈回溯和资源清理行为),也就给编译器更大的优化空间。

  • 提升性能:vector的push_back函数在扩容时,如果移动构造函数是noexcept形式时(is_nothrow_move_constructible_v)将使用移动来转移原有数据,而非之前的拷贝完成再删除的方式。使用“能移动则移动,必须拷贝再拷贝”的策略来提升性能。

注意事项

  • 只有在时间维度上恒为不发射异常的函数才可标注为noexcept,否则不要做出该函数noexcept的假设。

  • 如果函数标注为noexcept,则该函数调用的所有函数应也是noexcept,否则不要做出该函数noexcept的假设。尽管noexcept调用非noexcept函数会通过编译但不推荐这样做。

  • 不要为了使函数满足noexcept而修改函数,大可不必。

  • 释放内存的函数和析构函数默认为noexcept

6.总结

        综上所述,C++11通过引入noexcept关键字、智能指针、移动语义等特性,以及增强STL和其他库,显著提高了C++的异常安全性。这些特性使程序员能够更好地管理资源、避免资源泄漏和未定义行为,并在异常发时代码的健壮性和可靠性。

noexcept

相关文章:

C++之noexcept

目录 1.概述 2.noexcept作为说明符 3.noexcept作为运算符 4.传统throw与noexcept比较 5.原理剖析 6.总结 1.概述 在C中&#xff0c;noexcept是一个关键字&#xff0c;用于指定函数不会抛出异常。如果函数保证不会抛出异常&#xff0c;编译器可以进行更多优化&#xff0c;…...

Kafka之Broker原理

1. 日志数据的存储 1.1 Partition 1. 为了实现横向扩展&#xff0c;把不同的数据存放在不同的 Broker 上&#xff0c;同时降低单台服务器的访问压力&#xff0c;我们把一个Topic 中的数据分隔成多个 Partition 2. 每个 Partition 中的消息是有序的&#xff0c;顺序写入&#x…...

RabbitMQ docker安装及使用

1. docker安装RabbitMQ docker下载及配置环境 docker pull rabbitmq:management # 创建用于挂载的目录 mkdir -p /home/docker/rabbitmq/{data,conf,log} # 创建完成之后要对所创建文件授权权限&#xff0c;都设置成777 否则在启动容器的时候容易失败 chmod -R 777 /home/doc…...

篇3:Mapbox Style Specification

接《篇2:Mapbox Style Specification》,继续解读Mapbox Style Specification。 目录 Spec Reference Root 附录: MapBox Terrain-RGB...

C#WPF数字大屏项目实战11--质量控制

1、区域划分 2、区域布局 3、视图模型 4、控件绑定 5、运行效果 走过路过&#xff0c;不要错过&#xff0c;欢迎点赞&#xff0c;收藏&#xff0c;转载&#xff0c;复制&#xff0c;抄袭&#xff0c;留言&#xff0c;动动你的金手指&#xff0c;财务自由...

第九十七节 Java面向对象设计 - Java Object.Finalize方法

Java面向对象设计 - Java Object.Finalize方法 Java提供了一种在对象即将被销毁时执行资源释放的方法。 在Java中&#xff0c;我们创建对象&#xff0c;但是我们不能销毁对象。 JVM运行一个称为垃圾收集器的低优先级特殊任务来销毁不再引用的所有对象。 垃圾回收器给我们一个…...

【scikit-learn009】异常检测系列:单类支持向量机(OC-SVM)实战总结(看这篇就够了,已更新)

1.一直以来想写下机器学习训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架OCSVM模型相关知识体系。 3.欢迎批评指正,欢迎互三,跪谢一键三连! 4.欢迎…...

网络管理与运维

文章目录 网络管理与运维概念&#xff1a;传统网络管理&#xff1a;基于SNMP集中管理&#xff1a;基于iMaster NCE的网络管理&#xff1a;传统网络管理方式&#xff1a; 基于SNMP集中管理&#xff1a;交互方式&#xff1a;MIB&#xff1a;版本&#xff1a;SNMPv3配置网管平台&a…...

数据库查询字段在哪个数据表中

问题的提出 当DBA运维多个数据库以及多个数据表的时候&#xff0c;联合查询是必不可少的。则数据表的字段名称是需要知道在哪些数据表中存在的。故如下指令&#xff0c;可能会帮助到你&#xff1a; 问题的处理 查找sysinfo这个字段名称都存在哪个数据库中的哪个数据表 SELEC…...

第 400 场 LeetCode 周赛题解

A 候诊室中的最少椅子数 计数&#xff1a;记录室内顾客数&#xff0c;每次顾客进入时&#xff0c;计数器1&#xff0c;顾客离开时&#xff0c;计数器-1 class Solution {public:int minimumChairs(string s) {int res 0;int cnt 0;for (auto c : s) {if (c E)res max(res, …...

数据结构与算法之Floyd弗洛伊德算法求最短路径

目录 前言 Floyd弗洛伊德算法 定义 步骤 一、初始化 二、添加中间点 三、迭代 四、得出结果 时间复杂度 代码实现 结束语 前言 今天是坚持写博客的第18天&#xff0c;希望可以继续坚持在写博客的路上走下去。我们今天来看看数据结构与算法当中的弗洛伊德算法。 Flo…...

Ubuntu系统设置Redis与MySQL登录密码

Ubuntu系统设置Redis与MySQL登录密码 在Ubuntu 20.04系统中配置Redis和MySQL的密码&#xff0c;您需要分别对两个服务进行配置。以下是详细步骤&#xff1a; 配置Redis密码 打开Redis配置文件: Redis的配置文件通常位于/etc/redis/redis.conf。 sudo nano /etc/redis/redis.c…...

数据库连接池的概念和原理

目录 一、什么是数据库连接池 二、数据库连接池的工作原理 1.初始化阶段&#xff1a; 2.获取连接&#xff1a; 3.使用连接&#xff1a; 4.管理和优化&#xff1a; 三、数据库连接池的好处 一、什么是数据库连接池 数据库连接池&#xff08;Database Connection Pooling&…...

国内常用的编程博客网址:技术资源与学习平台

一、国内常用的编程博客网址&#xff1a;技术资源与学习平台 大家初入编程&#xff0c;肯定会遇到各种各样的问题。我们除了找 AI 工具以外&#xff0c;我们还能怎么迅速解决问题呢&#xff1f; 大家可以通过谷歌&#xff0c;百度&#xff0c;必应&#xff0c;github&#xf…...

怎么给三极管基极或者MOS管栅极接下拉电阻

文章是瑞生网转载&#xff0c;PDF格式文章下载&#xff1a; 怎么给三极管基极或者MOS管栅极接下拉电阻.pdf: https://url83.ctfile.com/f/45573183-1247189078-52e27b?p7526 (访问密码: 7526)...

Java Web学习笔记5——基础标签和样式

<!DOCTYPE html> html有很多版本&#xff0c;那我们应该告诉用户和浏览器我们现在使用的是HMTL哪个版本。 声明为HTML5文档。 字符集&#xff1a; UTF-8&#xff1a;现在最常用的字符编码方式。 GB2312&#xff1a;简体中文 BIG5&#xff1a;繁体中文、港澳台等方式…...

01_深度学习基础知识

1. 感知机 感知机通常情况下指单层的人工神经网络,其结构与 MP 模型类似(按照生物神经元的结构和工作原理造出来的一个抽象和简化了模型,也称为神经网络的一个处理单元) 假设由一个 n 维的单层感知机,则: x 1 x_1 x1​ 至 x n x_n xn​ 为 n 维输入向量的各个分量w 1 j…...

60、最大公约数

最大公约数 题目描述 给定n对正整数ai,bi&#xff0c;请你求出每对数的最大公约数。 输入格式 第一行包含整数n。 接下来n行&#xff0c;每行包含一个整数对ai,bi。 输出格式 输出共n行&#xff0c;每行输出一个整数对的最大公约数。 数据范围 1 ≤ n ≤ 1 0 5 , 1≤n≤…...

设计模式在芯片验证中的应用——迭代器

一、迭代器设计模式 迭代器设计模式(iterator)是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等数据结构&#xff09; 的情况下遍历集合中所有的元素。 在验证环境中的checker会收集各个monitor上送过来的transactions&#xff0…...

imx6ull - 制作烧录SD卡

1、参考NXP官方的手册《i.MX_Linux_Users_Guide.pdf》的这一章节&#xff1a; 1、SD卡分区 提示&#xff1a;我们常用的SD卡一个扇区的大小是512字节。 先说一下i.MX6ULL使用SD卡启动时的分区情况&#xff0c;NXP官方给的镜像布局结构如下所示&#xff1a; 可以看到&#xff0c…...

使用chatgpt api快速分析pdf

需求背景 搞材料的兄弟经常要分析pdf&#xff0c;然后看到国外有产品是专门调用chatpdf来分析pdf的&#xff0c;所以就来问我能不能帮他也做一个出来。正好我有chatgpt的api&#xff0c;所以就研究了一下这玩意怎么弄。 需求分析 由于chatgpt是按字符算钱的&#xff0c;所以…...

Vue:状态管理pinia

安装 npm install pinia在 main.js 中注册 // main.jsimport { createApp } from vue import { createPinia } from "pinia"; import App from ./app.vueconst app createApp(App) const pinia createPinia(); app.use(pinia).mount(#app)创建 store // stores/…...

【Android Studio】导入import android.support.v7.app.AppcompatActivity;时报错

一、问题描述 在进行安卓项目开发时使用import android.support.v7.app.AppcompatActivity;报错&#xff1a; 运行后会有乱码出现&#xff1a; 二、解决办法 将import android.support.v7.app.AppcompatActivity;改为import androidx.appcompat.app.AppCompatActivity;基本上…...

汽车区域控制器技术分析

汽车区域控制器的起源与发展 随着汽车技术的不断发展,汽车电子电气架构也在经历着深刻的变革。汽车区域控制器作为一种新兴的技术,正逐渐成为汽车电子电气架构的重要组成部分。 在早期,汽车电子电气架构主要采用分布式架构。这种架构下,各个电子控制单元(ECU)分别负责不…...

myEclipse新手使用教程

myEclipse新手使用教程 一、引言 myEclipse是一款流行的Java集成开发环境&#xff08;IDE&#xff09;&#xff0c;它集成了众多的开发工具&#xff0c;为Java开发者提供了一个强大的开发平台。本文将详细介绍如何下载、安装和配置myEclipse&#xff0c;以及如何创建一个简单…...

【WPF编程宝典】第6讲:资源

研究了 WPF 资源系统使得在应用不同部分可以重用相同对象的原理&#xff0c;介绍了如何在代 码和标记中声明资源&#xff0c;如何提取系统资源&#xff0c;以及如何使用类库程序集在应用程序之间共享资源。 1.资源基础 1.1静态资源和动态资源 区别&#xff1a;静态资源只从资…...

容器化部署Pig微服务快速开发框架

系统说明 基于 Spring Cloud 、Spring Boot、 OAuth2 的 RBAC 企业快速开发平台&#xff0c; 同时支持微服务架构和单体架构 提供对 Spring Authorization Server 生产级实践&#xff0c;支持多种安全授权模式 提供对常见容器化方案支持 Kubernetes、Rancher2 、Kubesphere、E…...

Windows编程:图标资源、光标资源、字符串资源、加速键资源、WM_PAINT消息、绘图

承接前文&#xff1a; win32窗口编程windows 开发基础win32-注册窗口类、创建窗口win32-显示窗口、消息循环、消息队列win32-鼠标消息、键盘消息、计时器消息、菜单资源 本文目录 图标资源光标资源WM_SETCURSOR 消息 字符串资源加速键资源WM_PAINT 消息绘图绘图编程绘图基础基…...

【2024 短剧0元轻资产创业风口】做自己的老板,做新媒体的领路人

好省短剧邀请码2Urux1ZoQm(长按复制粘贴即可)大多数好省短剧推广活动都会通过官方渠道发布邀请码。您可以通过关注官方社交媒体账号、订阅电子邮件通知或参与官方网站上的活动,获得邀请码的机会。官方渠道通常会提前公布邀请码的获取方式和条件,您只需按照要求执行即可。好省…...

Docker安装Bitbucket

centos7版本 [rootlocalhost ~]# cat /etc/os-release NAME"CentOS Linux" VERSION"7 (Core)" ID"centos" ID_LIKE"rhel fedora" VERSION_ID"7" PRETTY_NAME"CentOS Linux 7 (Core)" ANSI_COLOR"0;31"…...

深圳做网站最/免费刷seo

为了测试方便和直观&#xff0c;我们需要先创建一张测试表并插入一些数据&#xff1a;CREATE TABLE shop (id int(11) NOT NULL AUTO_INCREMENT COMMENT 记录ID,shop_id int(11) NOT NULL COMMENT 商店ID,goods_id int(11) NOT NULL COMMENT 物品ID,pay_type tinyint(1) NOT NU…...

新疆网站建设大全/北京网站制作推广

自己做站点的时候&#xff0c;都看看收录和关键词排名什么的&#xff0c;所以打造的这个批量关键词查询工具。#encoding:utf-8import urllib,re,random,time,sys,StringIO,sockettry:import pycurlexcept:passfrom bs4 import BeautifulSoupscore{1: 28.56,2: 19.23,3: 10.20,4…...

东营市公司网站建设价格/线下推广方式都有哪些

这个CRM很牛逼、很强大&#xff0c;自定义编辑太强大&#xff0c;充分利用个性化设置以后几乎无需二次开发&#xff0c;大大降低实施成本。 如果你是个在这方面有悟性的人&#xff0c;花两、三天的时间就可以证实上面的说法。 软件&#xff1a;SuiteCRM - 开源、核心功能软件…...

大理州建设局网站门户网/东莞网络营销推广专业

0 前言1 动态代理 1.1 JDK动态代理1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法1.2.2 CGLIB的过滤功能2 Spring AOP中的动态代理机制 2.1 JdkDynamicAopProxy2.2 CglibAopProxy3 总结0 前言 前一个季度旅游TDC的Thames服务有几次宕机&#xff0c;根据组内原因认真查找发现是数…...

什么软件 做短视频网站好/青岛关键词网站排名

作为 OPPO 的顶级旗舰产品线&#xff0c;Find 系列在沉寂了几年后终于登台亮相&#xff0c;最终以一款全景屏 升降式摄像头的 Find X 重新回到消费者的视线中。在这个刘海屏的大浪潮中&#xff0c;OPPO 并没有采用这种外观向功能妥协的方式&#xff0c;而是另辟蹊径&#xff0…...

北京网站的建设/seo公司运营

文章目录 前言I、运行时期,断点ptrace,直接返回II、分析如何调用的ptrace,hook ptrace2.0 准备工作:砸壳2.1 编写 tweak 分析2.2 具体步骤2.2.1 debugserver2.2.2 分析如何调用的ptrace2.2.1 此案例的hook prace 的代码2.4 DemoIII、 修改 PT_DENY_ATTACHIV、通过tweak,替…...