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

Effective C++ 改善程序与设计的55个具体做法笔记与心得 3

三. 资源管理

13. 以对象管理资源

请记住

  • 为防止资源泄露,使用智能指针

14. 在资源管理类中小心copying行为

请记住

  • 复制RAII对象必须一并复制他所管理的资源,所以资源的copying行为决定RAII对象的copying行为
  • 普遍而常见的RAII class copying行为是:抑制copying、施行引用计数法(reference counting)。不过其他行为也都可能被实现。

解释
‌‌‌‌  RAII(资源获取即初始化)是C++中一个非常重要的概念,它用于管理对象生命周期内的资源分配和释放问题。

‌‌‌‌  对于复制RAII对象,首要问题就是如何处理它所管理的资源。实际上,资源的复制行为决定了RAII对象的复制行为,不同的策略会对管理资源的对象的复制产生不同的影响:

  • 抑制复制(Prohibit Copying):既简单又有效。在这种情况下,复制构造函数和赋值运算符通常被声明为private,并且不传递任何实现。这阻止了复制和赋值。这是一个好的默认行为,通常适用于管理不可共享资源的类(如文件、线程、互斥锁等)。
class Uncopyable {
private:Uncopyable(const Uncopyable&);Uncopyable& operator=(const Uncopyable&);
};
  • 引用计数(Reference Counting):这种方法允许复制,同时确保原始资源的生命周期恰到好处。具体来说,只有当最后一个引用被销毁时,才会清理底层资源。std::shared_ptr是一种典型的实现引用计数的RAII类。
std::shared_ptr<int> p(new int[10]);
std::shared_ptr<int> q = p;  // 引用计数增加
  • 深度复制(Deep Copying):在这种策略中,我们为每个RAII对象创建一份新的资源副本。这比引用计数更安全,但可能更为费时,因为它需要复制所有数据。

  • 转移资源所有权(Transfer Ownership):通过移动语义(C++11开始提供),可以将资源从一个对象转移到另一个对象,而不需要复制。这通常适用于管理大块资源的RAII对象,例如std::unique_ptr

根据特定的类管理的资源类型和预期的用途,可以选择适合的策略来处理RAII对象的复制行为。这是面向对象的设计的一个重要方面。

15. 在资源管理类中提供对原始资源的访问

请记住

  • APIs往往要求访问原始资源,所以每一个RAI class应该提供一个“取得其所管理之资源”的办法。
  • 对原始资源的访问可能经由显式转换或隐式转换。一般而言显示转换比较安全,但隐式转换对客户比较方便。

解释
‌‌‌‌  资源获取即初始化(RAII)的类确实经常需要提供获取其管理的资源的方式。这样的设计并不会违背RAII原则,因为资源的所有权仍然在RAII对象中,但一些情况下确实需要让程序员能够访问这些底层资源。

这些底层资源的访问方式主要分为两种:

  • 显式转换:这样的设计使得访问者必须显示地请求访问资源。这样可以减少因误用底层资源而导致的问题。std::unique_ptr就是一个很好的例子,它提供了.get()方法来显式获取底层的原始指针。
std::unique_ptr<int> p(new int());
int* raw = p.get();
  • 隐式转换:这提供了对使用者更为简单的访问方式,但是如果使用不当,可能带来风险。比如,std::shared_ptr可以被隐式转化为bool类型,这使得我们能够在条件语句中使用。
std::shared_ptr<int> p(new int());
if (p) {// 如果 p 管理着一个对象,那么将会执行这里的代码
}

‌‌‌‌  一般来说,显式转换更为安全,因为它强制要求使用者意识到他们正在直接操作底层资源。然而,隐式转换可以使代码更简洁,提供更好的用户体验。因此,应根据特定的使用场景和对安全性的要求来确定哪种方法更为合适。

16. 成对使用new和delete时要采取相同形式

请记住

  • 如果你在new表达式中使用[],必须在相应的delete表达式中也使用[]。
  • 如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。

解释
‌‌‌‌  在C++中,这个规则非常重要,因为不正确地使用new[]delete[]会导致未定义的行为。

  1. 当我们使用new[]来分配数组时,必须使用delete[]来删除该数组。如果我们只用delete,就可能会出现内存泄漏。
int* array = new int[10];
delete[] array; // 正确的使用方式
  1. 另一方面,当我们使用new分配单个元素时,必须使用delete(不带[])来删除。如果我们使用delete[]来删除非数组类型的指针,那也会导致未定义的行为。
int* single = new int();
delete single; // 正确的使用方式

‌‌‌‌  这组规则是相当重要的,因为它们涉及到C++运行时环境如何在堆上分配和管理内存。遵循这些规则不仅可以避免内存泄漏,也能防止程序因为错误的内存释放操作而崩溃。

newnew[]以及deletedelete[]的区别主要在于它们处理的数据结构和内存分配的方式:

  1. newdelete:这两个操作符主要用于分配和释放单个对象的内存。
int* p = new int;       // 分配一个整数的内存
delete p;               // 释放该整数的内存
  1. new[]delete[]:这两个操作符用于分配和释放数组的内存。
int* arr = new int[10]; // 分配10个整数的内存
delete[] arr;           // 释放这10个整数的内存

‌‌‌‌  对于这两对操作符,最重要的一点是必须配对使用。也就是说,我们不能使用new来分配内存然后使用delete[]释放内存,反之亦然。

‌‌‌‌  注意:newnew[]分配的内存不会被自动释放,我们需要手动调用相应的delete或者delete[]来释放这些内存,否则将导致内存泄漏。这是一个常见的编码错误,也是使用RAII(资源获取即初始化)技术的主要原因,它可以通过在对象的生命周期结束时自动释放其拥有的资源,从而防止内存泄漏。

17. 以独立语句将newed对象置入智能指针

请记住
‌‌‌‌  以独立语句将newed对象存储于智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄露。

解释
‌‌‌‌  智能指针主要的优点就是它可以保证在任何情况下,包括出现异常时,都可以正确地释放内存。在C++中,如果我们创建了一个普通的指针并使用new分配了内存,但在释放这个内存前出现了异常,那么这个内存就会泄露。

‌‌‌‌  由于异常可能在new之后的任何时间发生,所以我们无法确定何时捕获并处理这个异常。因此,为了避免内存泄露,我们应该尽快将这个指针转换为智能指针。如果我们在创建智能指针对象的同一条语句中使用new,那么即使出现异常,内存也会安全地释放。

std::unique_ptr<int> ptr(new int(10));    // 创建一个存储int的智能指针

‌‌‌‌  虽然将new和智能指针的初始化放在同一行更简洁,但为了避免new在智能指针接管之前就抛出异常导致的任何可能的资源泄露,提倡以独立语句将newed对象存储于智能指针内。如:

int* temp = new int(10);
std::unique_ptr<int> ptr(temp);    // 创建一个存储int的智能指针

‌‌‌‌  这样,即使在new和智能指针的初始化之间抛出异常,我们也可以保证delete temp;被调用,防止了内存泄漏。

相关文章:

Effective C++ 改善程序与设计的55个具体做法笔记与心得 3

三. 资源管理 13. 以对象管理资源 请记住&#xff1a; 为防止资源泄露&#xff0c;使用智能指针 14. 在资源管理类中小心copying行为 请记住&#xff1a; 复制RAII对象必须一并复制他所管理的资源&#xff0c;所以资源的copying行为决定RAII对象的copying行为普遍而常见的…...

苹果的后来者居上策略:靠隐私保护打脸微软

01.苹果与微软相比更注重用户隐私 我一直是Windows的忠实用户&#xff0c;但微软疯狂地将人工智能融入一切&#xff0c;让我开始觉得应该咬咬牙换成Mac。 自小我几乎只用Windows电脑&#xff0c;所以我对MacOS一直不太适应。虽然Windows 11有其缺点&#xff0c;但总的来说&am…...

java经典面试题--进程和线程的关系/区别

进程和线程的定义以及作用 进程:进程是操作系统分配资源的基本单位,是程序的一次执行过程,它包括了程序执行的上下文环境,包括程序代码、数据、系统资源&#xff08;内存、文件、设备等&#xff09;以及执行状态等信息&#xff0c;其作用是提供一个独立的执行环境&#xff0c;…...

Solr 日志系统7.4.0部署和迁移到本地,Core Admin 添加新的core报错

文章目录 Solr部署Docker部署二进制部署 Tips:Solr设置账号密码方法1&#xff1a;(不使用)方法2&#xff1a; Core Admin 添加新的core报错Solr数据迁移 Solr部署 Docker部署 docker run -d -p 8983:8983 --name solr solr:latest docker run -d -p 8983:8983 -v /opt/solr:/…...

前缀和+双指针,CF 131F - Present to Mom

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 131F - Present to Mom 二、解题报告 1、思路分析 很经典的一种把列看作cell 来进行双指针/递推的题型 我们考虑&#xff0c;可以预处理出原矩阵中的所有star 然后我们去枚举矩形的上下边界&#xff0c;把…...

HCIA-速查-ENSP模拟器2步清空配置

需求&#xff1a;清空模拟器配置 清空当前图中配置 步骤1&#xff1a;reset saved-configuration 后输入y确认 步骤2&#xff1a;reboot后输入n否认再输入y确认 验证已经清空配置...

优选算法刷题笔记 2024.6.10-24.6.20

一、双指针算法(快慢指针,对撞指针) 艹&#xff0c;CSDN吞了我是十三题笔记&#xff01;&#xff01;&#xff01; 二、滑动窗口(滑动窗口) 1、找到字符串中所有字母异位词 class Solution {public List<Integer> findAnagrams(String s, String p) {int[] hash1 new in…...

无需科学上网:轻松实现国内使用Coze.com平台自己创建的Bot(如何实现国内免费使用GPT-4o/Gemini等最新大模型)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 如何在国内使用 Coze.com 创建的 Bot 📒📝 创建Bot📝 实现国内使用📝 测试⚓️ 相关链接 ⚓️📖 介绍 📖 Coze.com 是一个强大的平台,允许用户创建各种类型的 Bot。然而,许多国内用户可能会遇到访问问题,导致无法…...

【车载开发系列】CAN通信总线再理解(中篇)

【车载开发系列】CAN通信总线再理解&#xff08;中篇&#xff09; 九. CAN总线标准十. CAN物理层十一. CAN数据链路层1&#xff09;CAN的通信帧类型2&#xff09;CAN的标准帧格式1. CAN ID2. 数据场 3&#xff09;CAN总线仲裁 十二. CAN应用层1&#xff09;CANopen2&#xff09…...

系统编程:互斥锁,条件变量

互斥锁 使用过程: 1,声明锁: pthread_mutex_t lock; 2,初始化锁:pthread_mutex_init(&lock,NULL); 3,在线程的方法函数中上锁和解锁:(成对出现) pthread_mutex_lock(&lock); pthread_mutex_unlock(&lock); 4,销毁锁:pthread_mutex_destroy(&lock); 代码示例:…...

蓝鹏测控公司全长直线度算法项目多部门现场组织验收

关键字:全场直线度算法,直线度测量仪,直线度检测,直线度测量设备, 6月18日上午&#xff0c;蓝鹏测控公司全长直线度算法项目顺利通过多部门现场验收。该项目由公司技术部、开发部、生产部等多个部门共同参与&#xff0c;旨在提高直线度测量精度&#xff0c;满足高精度制造领域需…...

使用Python进行音频处理

通常会使用wave模块。但是&#xff0c;如果您想要处理其他类型的音频文件&#xff0c;或者需要更高级的音频处理功能&#xff0c;您可能需要安装第三方库&#xff0c;如pydub、soundfile、numpy等。 import wave # 读取WAV文件 with wave.open(input.wav, rb) as wav_file: …...

家有老人小孩,室内灰尘危害大!资深家政教你选对除尘空气净化器

哈喽&#xff0c;各位亲爱的朋友们&#xff01;今天我们来聊聊每次大扫除时最让人头疼的问题——灰尘。你有没有发现&#xff0c;两天不打扫&#xff0c;桌子上就能积上一层灰&#xff1b;阳光一照&#xff0c;地板上的灰尘都在跳舞&#xff1b;整理被子的时候&#xff0c;空气…...

AI在创造与毁灭之间摇摆:音乐产业的机遇与挑战并存

AI到底在创造还是毁掉音乐&#xff1f; 最近一个月&#xff0c;轮番上线的音乐大模型&#xff0c;一举将素人生产音乐的门槛降到了最低&#xff0c;并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后&#xff0c;AI产品的版权归属于谁&#xff0c;创意产业要如何在AI的阴…...

Spring Boot集成 Spring Retry 实现容错重试机制并附源码

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…...

MDK-ARM 编译后 MAP 文件分析

本文配合 STM32 堆栈空间分布 食用更佳&#xff01; 一图胜千言。。。...

antv g6实现系统拓扑图

1 背景 为例描述各个服务、redis、mysql等之间的联系及其健康状态&#xff0c;构建系统拓扑图&#xff0c;考虑 g6 更适合处理大量数据之间的关系&#xff0c;所以我们采用g6来绘制前端的图形。 g6提供的支持&#xff1a; 节点/边类型多样&#xff0c;同样支持自定义对于节点…...

因路径规划异常导致导航停止 Failed to pass global plan to the controller

因路径规划异常导致导航停止 Failed to pass global plan to the controller 控制台错误信息: [ WARN] [1718875656.343893537, 93.698000000]: Transformed plan is empty. Aborting local planner! [ERROR] [1718875656.343922719, 93.698000000]: move_base.cpp:854 Faile…...

AOSP开发环境搭建

目录 一、安装虚拟机 二、安装Ubuntu 三、安装VMware tools 3.1、通用安装 3.2、Ubuntu22.04 中Drag and drop is not supported问题 四、安装依赖环境 4.1、安装git 4.2、下载Python3 4.3、解压Python3 4.4、编译与安装Python3 3.sudo make install 4.5、安装Pyth…...

React native新架构组成

React Native 的新架构&#xff08;New Architecture&#xff09;引入了一些新的组件和概念&#xff0c;旨在提高性能、增强灵活性和简化跨平台开发。主要组成部分包括&#xff1a; Fabric: Fabric Renderer: Fabric 是新的渲染引擎&#xff0c;它旨在取代现有的渲染引擎。与…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

用js实现常见排序算法

以下是几种常见排序算法的 JS实现&#xff0c;包括选择排序、冒泡排序、插入排序、快速排序和归并排序&#xff0c;以及每种算法的特点和复杂度分析 1. 选择排序&#xff08;Selection Sort&#xff09; 核心思想&#xff1a;每次从未排序部分选择最小元素&#xff0c;与未排…...

python读取SQLite表个并生成pdf文件

代码用于创建含50列的SQLite数据库并插入500行随机浮点数据&#xff0c;随后读取数据&#xff0c;通过ReportLab生成横向PDF表格&#xff0c;包含格式化&#xff08;两位小数&#xff09;及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...

IP选择注意事项

IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时&#xff0c;需要考虑以下参数&#xff0c;然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...

从数据报表到决策大脑:AI重构电商决策链条

在传统电商运营中&#xff0c;决策链条往往止步于“数据报表层”&#xff1a;BI工具整合历史数据&#xff0c;生成滞后一周甚至更久的销售分析&#xff0c;运营团队凭经验预判需求。当爆款突然断货、促销库存积压时&#xff0c;企业才惊觉标准化BI的决策时差正成为增长瓶颈。 一…...