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

effective c++阅读之旅---条款29

为"异常安全"而努力是值得的!

什么是异常安全?
所谓的"异常安全",往往值得是函数接口的异常安全,它要求函数满足两个条件:
异常抛出时:

1、不泄露任何资源
2、不允许数据被破坏

异常安全分为哪些情况呢?
答:一共由三种情况。1、基本保证 2、强烈保证 3、nothrow保证

1、基本保证什么意思?
异常被抛出,所有数据仍然处于有效状态,对象处于内部的前后一致。但现实状态无法预料

2、强烈保证什么意思?
异常被抛出,如果成功,就是完全成功;如果失败,就回复到之前的状态

3、nothrow保证什么意思?
保证绝不抛出任何异常,总是能够成功。常作用域内置类型(int、指针等)

举例如下:
有个class用来表示带背景图案的GUI菜单,它希望用于多线程环境。

class Menu
{
public:void changeBackground(std::istream& imSrc); //改变背景
private:Mutex mutex;      //互斥锁Image* bgImage;   //背景图片int imageChanges; //背景改变次数
}void Menu::changeBackground(std::istream& imSrc)
{lock(&mutex);delete bgImage; // flag ++imageChanges;bgImage = new Image(imSrc);unlock(&mutex);
}

从异常安全性来看,这个函数很糟糕,一个条件都没有满足:

  • (1)、假设 flag 处抛出异常,则原本对象的数据被破坏
  • (2)、因为抛出异常,导致已经lock的互斥锁也没有释放,永远处于加锁状态

那么如何解决(1)的问题?
通过RAII手法,对资源进行封装的使用。
例如:

void Menu::changeBackground(std::istream& imSrc)
{Lock m(&mutex);  //Lock包裹互斥锁delete bgImage; // flag ++imageChanges;bgImage = new Image(imSrc);
}

如何解决(2)的问题?
合理并巧妙的安排代码语句的顺序。

class Menu
{
public:void changeBackground(std::istream& imSrc); //改变背景
private:Mutex mutex;      //互斥锁std::shared_ptr<Image> bgImage;   //背景图片int imageChanges; //背景改变次数
}void Menu::changeBackground(std::istream& imSrc)
{Lock m(&mutex);  //Lock包裹互斥锁bgImage.reset(new Image(imSrc)); //这里如果new失败,内部并不会改变原本的bgImage数据++imageChanges;
}

上述几乎已经能够达到强烈保证的要求了,但是唯独有一个点没有考虑到,如果Image的构造函数抛出异常,那么原本的istream的流数据状态已经发生改变,所以上述只能算是基本承诺

那么有什么好的方法能够弥补这一缺陷呢?
通过copy-and-swap技术!
它的原理就是:
1、为打算修改的对象做出一份副本
2、对副本做相应需要的修改
3、将副本和原本的对象进行swap置换

注: 往往针对数据修改的swap,需要数据本身在一个类中,并且拥有这个类实例化的指针才行

举例:

struct PMImpl
{std::shared_ptr<Image> bgImage;int imageChanges;
}class Menu
{
public:void changeBackground(std::istream& imSrc); //改变背景
private:Mutex mutex;      //互斥锁std::shared_ptr<PMImpl> pImpl;
}void Menu::changeBackground(std::istream& imSrc)
{Lock m(&mutex);  //Lock包裹互斥锁std::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl)); //1、拷贝副本pNew->bgImage.reset(new Image(imSrc));  //2、对副本修改++pNew->imageChanges;using std::swap;swap(pNew,pImpl); //3、进行swap置换
}

综上,这样基本上就达成了我们的强烈保证的目的了

结尾: 我是航行的小土豆,喜欢我的程序猿朋友们,欢迎点赞+关注哦!希望大家多多支持我哦!有相关不懂问题,可以留言一起探讨哦!

如有引用或转载记得标注哦!

相关文章:

effective c++阅读之旅---条款29

为"异常安全"而努力是值得的&#xff01; 什么是异常安全&#xff1f; 所谓的"异常安全"&#xff0c;往往值得是函数接口的异常安全&#xff0c;它要求函数满足两个条件&#xff1a; 异常抛出时&#xff1a; 1、不泄露任何资源 2、不允许数据被破坏 异常安…...

Android system — 进程生命周期与ADJ

Android system — 进程oom_adj0. 引言1. 进程的生命周期1.1 Foreground process1.2 Visible process1.3 Service process1.4 Background process1.5 Empty process2. Lowmemorykiller2.1 ADJ级别2.2 进程state级别2.3 lmk策略2.4 如何查看应用oom_adj值3. 注意0. 引言 本文主要…...

vue3+ts+node个人博客系统(三)

一.主页顶部和中心面板布局 &#xff08;1&#xff09; 首先先去element-plus选择合适的布局el-container (2)在头部处编写相应的菜单栏el-menu,在这里要注意动态绑定路由的问题:default-active"$route.path"。将default-active设置为$route.path&#xff0c;el-me…...

Python第三方模块

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…...

怎样查询PMP成绩?

【如何查询成绩】1、输入网址&#xff08;PMI官网&#xff0c;不知道网址的私戳&#xff09;&#xff0c;点击 Log In如果忘记 PMI 的账号和密码了&#xff0c;怎么办&#xff1f;可以在你报名机构官网的个人中心的学习中心的我的报名处查看 PMI 的注册名和密码2、点击 Exam An…...

说说变量 __name__ 和它可能取到的一个值 __main__

结合 例子 弄懂 变量__name__ 和它的值’ main’这两个东西。 首先&#xff0c;明白两个定义&#xff0c; __name__是一个变量&#xff0c; __main__是个普通字符串&#xff0c;不是变量&#xff0c;但可以作为变量的值。 例子&#xff1a; 1.py 代码如下&#xff1a; if _…...

软考高级-信息系统管理师之整体管理(最新版)

整体管理 1、项目整体管理概述2、制定项目章程(选择,案例,论文)制定项目章程过程制定项目章程的依据1、协议2.项目工作说明书:3、商业论证4、事业环境因素包括,但不限于如下事项。5、组织过程资产:项目选择方法项目启动会议项目目标引导技术3、制订项目管理计划(选择)项目管…...

JVM学习篇垃圾收集器ParNewCMS与底层三色标记算法详解

1. 垃圾收集算法 2. 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法&#xff0c;这种算法没有什么新的思想&#xff0c;只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代&#xff0c;这样我们就可以根据各个年代的特点选择合适的垃圾收集算法…...

基于FFmpeg和Screen Capturer Recorder实现屏幕和声音的录制

当我们看到一些精彩的视频画面&#xff0c;但无法下载时&#xff0c;可以通过录屏的方式将视频和音频录制下来。 这个时候我们需要安装采集视频和音频的工具screen-capture-recorder。 以下是在windows10环境下&#xff0c;基于FFmpeg和Screen Capturer Recorder实现屏幕和声音…...

猿人学14题详解

目测重点在于cookie&#xff1a;mz和m 获取mz.js: https://match.yuanrenxue.com/static/match/match14/m.js 获取设置m&#xff1a; https://match.yuanrenxue.com/api/match/14/m 一、还原16进制 const fs require(fs); const parser require(babel/parser); const gen…...

Allegro如何快速把推挤的走线变平滑操作指导

Allegro如何快速把推挤的走线变平滑操作指导 Allegro有个非常强大的功能,推挤命令,可以快速的让走线以不报DRC的形式避让目标 推挤后的效果如下图 但是走线不够平滑,如果每一段都去再推一下比较费时间,下面介绍allegro本身自带的优化类似走线的功能 具体操作如下 点击Rout…...

nginx基础学习

作为前端开发者&#xff0c;也很有必要了解一些运维部署知识。 nginx的作用有哪些&#xff1f; 负载平衡动静分离反向代理 何为反向代理&#xff1f; 反向代理即是&#xff0c;用户访问nginx服务器&#xff0c;nginx又将请求转发到真正服务器上&#xff0c;为什么用户不能直…...

【HDFS】FsDatasetImpl#recoverClose方法

recoverClose的目的recoverClose的过程recoverClose的调用点一、前言 HDFS客户端写文件时,如果某个datanode发生错误或者异常。客户端会把这个datanode从pipeline里踢除,然后进行pipiline recovery,用剩余datanodes去写或者满足一定的条件时补充新的datanode到pipeline中写…...

加油站会员管理小程序实战开发教程15 完结篇

这篇是本次实战课程的最后一篇,我们在上篇还有两个问题没解决。一个是会员卡类型显示不对,一个是不同的会员卡我们希望背景色显示不同。我们先处理一下这两个问题 1 显示会员卡类型 在列表上直接显示会员卡类型,目前显示的是数字,这个是因为枚举类型导致的。枚举类型在数…...

学习 Python 之 Pygame 开发坦克大战(五)

学习 Python 之 Pygame 开发坦克大战&#xff08;五&#xff09;坦克大战完善地图1. 创建砖墙2. 给砖墙增加子弹击中的碰撞效果3. 给砖墙添加坦克不能通过的碰撞效果4. 添加石墙5. 添加玩家基地6. 最终效果坦克大战完善地图 我的素材放到了百度网盘里&#xff0c;里面还有原版…...

【ROS】Windows系统安装ROS体验

大家平时玩ROS都是在Ubuntu系统上&#xff0c;那Windows系统可以安装吗&#xff0c;答案是&#xff1a;可以的&#xff01;Windows为了发展自家的物联网生态&#xff0c;已经在Windows系统支持ROS了。 文章目录1.安装VS 20172.安装Chocolatey & Git3.安装ROS4.运行ROS例程1…...

第1讲-初步认识数据库系统(测试题总结)

一、测试题 数据库系统 包含 数据库管理系统 详细版&#xff1a; 数据库管理系统DBMS是数据管理软件&#xff0c;在用户和操作系统之间。 数据库系统DBS由数据库&#xff0c;数据库管理系统&#xff08;及其应用开发工具&#xff09;、应用程序和数据库管理员DBA组成的存储、管…...

进程-操作系统结构

进程-操作系统结构 中文仅本人理解&#xff0c;有错误请联系我。 操作系统为不同方面服务&#xff0c;有不同的设计角度。 为用户&#xff1a; 使用 为程序员&#xff1a;创造 程序员需要关注的就是system call接口的调度 file systems&#xff1a;ntfs&#xff0c;ext4 commu…...

【网络原理6】数据链路层协议——以太网

数据链路层负责的是相邻两个网络节点之间的数据以帧为单位进行传输。 具体关于数据链路层的介绍&#xff0c;已经在这一篇文章当中提到了。 初识网络&#xff1a;IP、端口、网络协议、TCP-IP五层模型_革凡成圣211的博客-CSDN博客TCP/IP五层协议详解https://blog.csdn.net/weix…...

组合数学原理与例题

目录 一、前言 二、计数原理 1、加法原理 2、分割立方体&#xff08;lanqiaoOJ题号1620&#xff09; 3、乘法原理 4、挑选子串&#xff08;lanqiaoOJ题号1621&#xff09; 5、糊涂人寄信&#xff08;lanqiaoOJ题号1622&#xff09; 6、战斗吧N皇后&#xff08;lanqiaoO…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...