Effective C++读书笔记之为“异常安全”而努力是值得的

告别PlatformIO!用Arduino IDE搞定ESP32上的micro-ROS 2.0.5(Humble版) 本文详细介绍了如何从PlatformIO迁移到Arduino IDE以支持ESP32上的micro-ROS 2.0.5(Humble版)。内容涵盖环境配置、项目转换、常见问题解决及高级优化技巧,帮助开发者顺利过渡并充分利用Arduino IDE的官方支持优势。 阅读详情

先来看一段代码,假设有一个class用来表现夹带背景图案的GUI菜单
 class PrettyMenu {
 public:
  .....
  void changeBackground(std::istream& imgSrc); //改变背景图案
 private:
  Mutex mutex;         //互斥器 用于多线程环境
  Image* bgImage;      //目前的背景图像
  int imageChanges;    //背景图像被改变的次数
 };
 void PrettyMenu::changeBackground(std::istream& imgSrc)
 {
  lock(&mutex);                //取得互斥器
  delete bgImage;              // 摆脱旧的背景图像
  ++imageChanges;              //修改图像变更次数
  bgImage = new Image(imgSrc); //安装新的图像
  unlock(&mutex);              //释放互斥器
 }
 从“异常安全性”来看这个函数很差。“异常安全”有两个条件,当异常被抛出时,带有异常安全性的函数会:
 1) 不泄露任何资源
 上面的函数没有做到这点,一旦"new Image(imgSrc)"异常了,对unlock的调用就不会执行了,于是互斥器资源被泄露
 2) 不允许数据败坏
 还是上面的函数,一旦"new Image(imgSrc)"异常了,bgImage就是指向一个已被删除的对象,imageChanges也已被累加,而其实没有新的图像被成功安装起来。
 解决方法:
 1) 对于资源泄露我们前面讨论过--使用对象来管理资源,如:
 void PrettyMenu::changeBackground(std::istream& imgSrc)
 {
  Lock m1(&mutex);             //利用Lock的对象来管理资源--互斥器
  delete bgImage;              // 摆脱旧的背景图像
  ++imageChanges;              //修改图像变更次数
  bgImage = new Image(imgSrc); //安装新的图像
 }
 2) 如何保证数据不被破坏 先来看一下异常安全函数的三个级别:
 a 基本承诺
 如果异常抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。
 b 强烈保证
 如果异常抛出,程序状态不改变。即如类函数成功,就是完全成功,如果函数失败,程序回复到调用函数之前的状态
 c 不抛掷(nothrow)保证
 承诺绝不抛出异常,因为它们总是能够完成原先承诺的功能。作用于内置类型(如int等)的操作都提供nothrow保证。
 异常安全码(Exception-safe code)必须提供上述三种保证之一。否则,它就不是异常安全的。我们的所要做的就是根据我们的代码要求,选择一种级别来实现相应的异常安全的代码。
 一般来说,你希望提供nothrow函数,这个是异常安全最好的状态。可是这个往往都办不到。可能的话请得供nothrow保证。
 现在我们给出一个针对上面的函数的异常安全的强烈保证的例子:
 方案一 首先使用智能指针,之后调整函数内的语句顺序
 class PrettyMenu {
  ...
  sdt::trl::shared_ptr<Image> bgImage;    //使用智能指针
 };
 void PrettyMenu::changeBackground(std::istream& imgSrc)
 {
  Lock ml(&mutex);
  bgImage.reset(new Image(imgSrc));  //这里不需要手动delete旧图像,因为智能指针内部处理好了
  ++imageChange;                     //更新图像后才累加imageChange
 }
 方案二 这里还有一个一般化的设计策略,就是copy and swap。原则很简单:为你打算修改的对象做出一个副本,然后在那副本身上做一切必要修改。若有任何修改动作抛出异常,原对象仍保持未改变状态。待所有改变都成功后,再将修改过的那个副本和原对象在一个不抛出异常的操作中置换(swap)。
 具体的做法,还会使用到pimpl idiom,即把隶属对象的数据从原对象放进另一个对象内,然后赋予原对象一个指针,指向那个实现的对象(implementation object)。如:
 struct PMImpl {    //原对象的数据成员
  std::trl::shared_ptr<Image> bgImage;
  int imageChanges;
 };
 class PrettyMenu {
 
 private:
  Mutex mutex;         //互斥器 用于多线程环境
  sdt::trl::shared_ptr<PMImpl> pImpl; 
 };
 void PrettyMenu::changeBackground(std::istream& imgSrc)
 {
  usint std::swap;
  Lock ml(&mutex);
  sdt::trl::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl)); //获取副本
  pNew->bgImage.reset(new Image(imgSrc)); //修改副本
  ++pNew->imageChagnes;
  swap(pImpl, pNew);      //交换原对象和副本,释放mutex             
 }
 copy and swap保证了对对象状态做出了全有全无改变的一个很好办法,可是它的效率不是很高。
 
 当你在写新码和修改旧码时,请仔细想想如何让它具备异常安全性。首先是以对象管理资源,那可阻止资源泄露。然后是挑选三个异常安全保证中的某一个实施于你所写的每一个函数身上。

 总结:
 1) 异常安全函数(Exception safe functions)即使发生异常也不会泄露资源或允许任何数据结构败坏。这样的函数区分为三种可能的保证:基本型,强烈型,不抛异常型
 2) “强烈保证”往往能够以copy and swap实现出来,但“强烈保证”并非对所有函数都可实现或具备现实意义
 3) 函数提供的“异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证”中的最弱者

SAP UI5 本地开发工具 fiori-tools-proxy 中间件详解及使用场景 该中间件基于 http-proxy-middleware 库实现,分为 ui5 资源代理和 backend 代理两大模式,并可与 fiori run 或 ui5 serve 命令无缝集成,通过配置 ui5.path、ui5.url 以及 backend.path、backend.url 等参数,实现与目标系统的灵活对接和安全配置 (就后端系统代理而言,fiori-tools-proxy 内置 @sap-ux/backend-proxy-middleware,可将以指定前缀(如。 阅读详情

相关推荐

VS2022跨平台开发实战:SSH远程调试Linux程序全攻略

本文详细介绍了如何使用Visual Studio 2022进行跨平台开发,通过SSH协议远程调试部署在Linux服务器上的C/C++程序。文章提供了从环境搭建、连接配置、项目创建到编译调试的完整实战指南,帮助Windows开发者无缝衔接Linux环境,显著提升问题定位与开发效率。

weixin_28826521的博客 429

《Effective C++》读书笔记之item29:为“异常安全”而努力是值得的

1.“异常安全性”(exception safety)能够为函数带来两个好处: 不泄漏任何资源;不允许数据败坏:操作未正确完成却已经改变了部分数据。 以这样的思想设计的函数(异常安全性函数)提供以下三个保证,即具有三个安全性等级: 基本承诺:如果抛出异常,程序内的任何事物仍然保持在有效状态下,没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。但程序的现实状态不

banguijun的专栏 870

从零到一:银河麒麟OS下C#跨平台开发的避坑指南

本文详细介绍了在银河麒麟OS下进行C#跨平台开发的完整流程,从开发环境搭建到避坑指南。针对国产操作系统特性,提供了.NET Core安装、开发工具链配置、桌面应用开发及部署优化的实战经验,特别关注ARM架构适配和性能调优,帮助开发者高效应对国产化开发挑战。

weixin_29221753的博客 863

读书笔记《Effective C++》条款29:为“异常安全”而努力是值得的

异常安全函数提供以下三个保证之一: 1.基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。 2.强烈保证:如果异常被抛出,程序状态不改变。调用这样的函数需有这样的认知:如果函数成功,就是完全成功;如果函数失败,程序会回复到“调用函数之前”的状态。 3.不抛掷(nothrow)保证:承诺绝不抛出异常,因为它

Do-Program的专栏 382

iOS 取证窍门:为什么要先从 Recovery 恢复模式开始?

未记录的 DFU 代表“设备固件升级”。与专为普通用户设计的恢复模式不同,DFU 模式从来都不是为公众设计的。Apple 知识库中的任何地方都没有关于 DFU 的文档。进入 DFU 的方法主要是通过按下、按住和释放按钮的复杂操作序列,并具有精确的时间限制。在多个步骤中的任何一个步骤中,如果时间错误,都会导致重新启动设备,而不是将其切换到 DFU。另外,设备屏幕上也没有 DFU 模式的指示。如果设备成功切换到 DFU,显示屏将保持黑色。即使对于专家来说,进入 DFU 模式也可能很困难。恢复模式是最容易解释的。

2302_82041293的博客 1198

ROS2机械臂实战:从基础控制到视觉抓取

本文详细介绍了ROS2机械臂从仿真环境搭建到视觉抓取的全流程实战指南。内容涵盖使用Gazebo搭建仿真环境、编写基础控制节点、集成视觉感知进行目标检测与坐标变换,并设计状态机逻辑实现自动化抓取。通过系统集成与联调,帮助开发者掌握ROS2机械臂开发的核心技能。

weixin_29197699的博客 448

Effective C++ | 读书笔记 (三)

提前定义变量,有可能导致变量并没有使用(如中间抛异常了),而平白多了一个构造和析构成本。但是循环怎么办?// 方式AWidget w;i < n;...// 方式Bi < n;++i) {...做法A:1个构造 + 1个析构 + n个赋值操作做法B:n个构造函数 + n个析构函数打破本条款选择A的依据:(1)你知道赋值成本比“构造+析构"成本低。(2)你正在处理代码中效率高度敏感的部分。否则你应该使用做法B,维持变量尽可能在使用时定义的原则。请记住。

m0_74795952的博客 945

三维点云孔洞修复(附Python代码和公共点云数据集链接)

(1)物体自身缺失(2)物体自身形状复杂,很多凹凸面不够规则甚至存在空腔,空腔内部无法被三维激光扫描仪扫描到(3)物体部分区域对激光扫描不敏感,未被扫描上(4)扫描仪的扫描稳定性。

yanghl1215的博客 6952

Effective C++_读书笔记

设计与声明。

Mr.Andy的博客 1460

Renesas:定时器输入捕获

一、PWM输入捕获 1、Smart Configurator配置 注意:在使用前,需要使能对应的定时器!否侧无法正常进行输入捕获! 2、脉冲宽度的获取 如何区分高低电平的脉冲宽度:最常用的方法就是在触发中断后,判断IO口的高低电平,来确认是上升沿触发的中断还是下降沿触发的中断。 若无法进入中断,可查看:Renesas:配置中断的常规流程 (1)中断方式(Smart Configurator生成的代码) #pragma interrupt r_Config_TAUB0_0_i...

不吃鱼的猫的博客 2479

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之BswM模块配置详解(上)

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之BswM模块配置详解(上)

weixin_42412049的博客 739

《Effective C++》读书笔记(一)

《Effective C++》读书笔记 条款01:视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分(C, Obejct-Oriented C++, Template C++, STL)。 条款02:尽量以const, enum, inline替换#define 对于单纯常量,最好以const对象或enum替换#define。 对于形似函数的宏,最好改用inline函数代替#define。 条款03:尽可能使用const 将某些东西声明为const可帮助

WINGREZ‘S BLOG 618

2025年下半年网络工程师案例分析真题及答案解析

2025年下半年网络工程师案例分析真题及答案解析

鹿鸣天涯 1088

Effective cpp 读书笔记6

26.尽可能延后变量定义时的出现时间 27.尽量少做转型动作 28.避免返回handles指向对象内部成分 29.为“异常安全”而努力使值得的 30.透彻了解“inlining”的里里外外 31.将文件间的编译依存关系降至最低

GZGlenn的博客 438

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

《Effective C++》读书笔记

《Effective C++》的目录方便回顾。 1.视c为一个语言联邦 2.尽量以constenuminline替换-define 3.尽可能使用const 4.确认对象被使用前已先被初始化 5.了解c默默编写并调用了哪些函数 6.若不想使用编译器自动生成的函数就该明确拒绝 7.为多态基类声明virtual析构函数 8.别让异常逃离析构函数 9.绝不在构造和析构过程中调用virtual函数 10.令operator-返回一个reference-to-this 11.在operator-中处理自我赋值 12.

江城的博客 416

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Effective C++ 读书笔记(十)

假设你的程序涉及到矩形,每个矩形又左上角和右下角表示。为了让矩形类尽可能小,我们可能需要一个辅助的struct来存放point类,再令Rectangle指向它。Rectangle的使用者必须能计算Rectangle的范围,所以这个类提供upperLeft和lowerRight函数。Point式个用户自定义类型,根据条款二十尽量以引用返回,于是这些函数返回引用。这样的设计尽管呢个通过编译,但是是错误的。一方面这两个函数被声明为const,因为其只是用来获取相关坐标点的方法,而不是修改数据。

qq_53660404的博客 885

Effective C++ 读书笔记总结

Effective C++ 读书笔记总结 一 、 书本目录 让自己习惯C++ 条款01:视C++为一个语言联邦 条款02:尽量以const,enums,inline替换#define 条款03:尽可能使用const 条款04:确定对象被使用前先被初始化 构造/析构/赋值运算 条款05:了解C++默默编写并调用哪些函数 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 条款07:为多...

qq_40028201的博客 395

《Effective C++》 读书笔记(详细总结55条款)下篇

Effective C++ 目录五、实现26、尽可能延后变量定义的时间27、尽量少做转型动作28、避免返回 Handles 指向对象内部成分29、为异常安全努力是值得的30、透彻理解 inlining 里里外外31、将文件间的编译依存关系降到最低六、继承与面向对象设计32、确定你的 public 继承塑模出is-a的关系33、避免遮掩继承而来的名称34、区分接口继承和实现继承35、考虑 virtual 函数以外的其他选择36、绝不重新定义继承而来的 non-virtual 函数七、模板与泛型编程八、定制

身在边城 心在编程 870

《Effective C++》读书笔记(二)

《Effective C++》读书笔记 条款26:尽可能延后变量定义式的出现时间 尽可能延后变量定义式的出现。这样做可增加程序的清晰度并改善程序效率。 条款27:尽量少做转型动作 如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。如果有个设计需要转型动作,试着发展无需转型的替代设计。 如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需要将转型放进他们自己的代码内。 尽量使用C+±style转型,不要使用旧式转型。前者很容易辨识出来,而且也比较有

WINGREZ‘S BLOG 427

Effective C++读书笔记(中)

Effective C++读书笔记(四到六章)

still_wtm的博客 524

effective C++读书笔记

effective C++读书笔记

frankwyw的博客 712

Effective C++ 读书笔记(五)

Effective C++ 读书笔记(五) 5、 实现 条款26: 尽可能延后变量定义式的出现时间 “尽可能延后”的意义,不仅仅是把变量定义延迟到变量的使用前一刻为止,甚至该尝试延后这份定义到能够给它赋初值为止,这样还可以避免无意义的default构造函数。即使用前定义并初始化 对于循环 A代码 Widget w;//定义在循环外 for(int i=0;i < n;++i) ...

qq_40028201的博客 355

effective c++读书笔记

effective c++读书笔记一级目录二级目录三级目录Charpter 1. 让自己习惯C++条款01: 视C++为一个语言联邦条款02: 尽量以const,enum,inline替换#define条款03: 尽可能使用const条款04: 确定对象被使用前已先被初始化Charpter 2. 构造/析构/赋值运算条款05: 了解C++默默编写并调用哪些函数条款06: 若不想使用编译器自动生成的函数,就该明确拒绝条款07: 为多态基类声明virtual析构函数条款08: 别让异常逃离析构函数条款09: 绝

cwdben的博客 548

读书笔记 effective c++ Item 29 为异常安全的代码而努力

异常安全在某种意义上来说就像怀孕。。。但是稍微想一想。在没有求婚之前我们不能真正的讨论生殖问题。 假设我们有一个表示GUI菜单的类,这个GUI菜单有背景图片。这个类将被使用在多线程环境中,所以需要mutex进行并发控制。 1 class PrettyMenu { 2 public: 3 ... 4 void changeBackground(std::istream& img

狼啸极行的博客 270

【读书笔记】【Effective C++】实现

【读书笔记】【Effective C++】实现。

做一些记录工作。 434

Effective C++ 读书笔记

1、让自己习惯C++ Accusoming Yourself to C++  条款01:视C++为一个语言联邦  条款02:尽量以const,enum,inline 替换 #define  条款03:尽可能使用const  条款04:确定对象被使用前先被初始化 2、构造/析构/赋值运算 Constructors,Destructors,and Assignment Operators  条款05:了解 C++ 默默编写并调用哪些函数  条款06:若不想使用编译器自动生成的函数,就该明确拒绝  条款07:为多

weixin_45867382的博客 198

《Effective C++读书笔记》--条款29:努力写出异常安全的代码

异常安全有两个条件: ①不泄漏任何资源 ②不允许数据破坏 对于资源泄漏的问题我们只要遵循以对象管理资源这条条款就很容易解决,对于数据败坏的问题,首先我们要知道异常安全函数的概念,异常安全函数提供以下三个保证之一: ①基本承诺:如果异常被抛出,程序内所有事物仍保持在有效状态下,没有任何对象或数据结构被破坏,所有对象都处于一种内部前后一致的状态。 ②强烈保证:如果异常被抛出,程序状态不改变。

WingC的博客 589
上一篇: Effective C++读书笔记之避免返回handles指向对象内部成分
下一篇: Effective C++读书笔记之透彻了解inlining的里里外外
anthit
博客等级 码龄21年 13粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值