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[]
会导致未定义的行为。
- 当我们使用
new[]
来分配数组时,必须使用delete[]
来删除该数组。如果我们只用delete
,就可能会出现内存泄漏。
int* array = new int[10];
delete[] array; // 正确的使用方式
- 另一方面,当我们使用
new
分配单个元素时,必须使用delete
(不带[]
)来删除。如果我们使用delete[]
来删除非数组类型的指针,那也会导致未定义的行为。
int* single = new int();
delete single; // 正确的使用方式
这组规则是相当重要的,因为它们涉及到C++运行时环境如何在堆上分配和管理内存。遵循这些规则不仅可以避免内存泄漏,也能防止程序因为错误的内存释放操作而崩溃。
new
和new[]
以及delete
和delete[]
的区别主要在于它们处理的数据结构和内存分配的方式:
new
和delete
:这两个操作符主要用于分配和释放单个对象的内存。
int* p = new int; // 分配一个整数的内存
delete p; // 释放该整数的内存
new[]
和delete[]
:这两个操作符用于分配和释放数组的内存。
int* arr = new int[10]; // 分配10个整数的内存
delete[] arr; // 释放这10个整数的内存
对于这两对操作符,最重要的一点是必须配对使用。也就是说,我们不能使用new
来分配内存然后使用delete[]
释放内存,反之亦然。
注意:new
和new[]
分配的内存不会被自动释放,我们需要手动调用相应的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. 以对象管理资源 请记住: 为防止资源泄露,使用智能指针 14. 在资源管理类中小心copying行为 请记住: 复制RAII对象必须一并复制他所管理的资源,所以资源的copying行为决定RAII对象的copying行为普遍而常见的…...
苹果的后来者居上策略:靠隐私保护打脸微软
01.苹果与微软相比更注重用户隐私 我一直是Windows的忠实用户,但微软疯狂地将人工智能融入一切,让我开始觉得应该咬咬牙换成Mac。 自小我几乎只用Windows电脑,所以我对MacOS一直不太适应。虽然Windows 11有其缺点,但总的来说&am…...
java经典面试题--进程和线程的关系/区别
进程和线程的定义以及作用 进程:进程是操作系统分配资源的基本单位,是程序的一次执行过程,它包括了程序执行的上下文环境,包括程序代码、数据、系统资源(内存、文件、设备等)以及执行状态等信息,其作用是提供一个独立的执行环境,…...
Solr 日志系统7.4.0部署和迁移到本地,Core Admin 添加新的core报错
文章目录 Solr部署Docker部署二进制部署 Tips:Solr设置账号密码方法1:(不使用)方法2: 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 来进行双指针/递推的题型 我们考虑,可以预处理出原矩阵中的所有star 然后我们去枚举矩形的上下边界,把…...
HCIA-速查-ENSP模拟器2步清空配置
需求:清空模拟器配置 清空当前图中配置 步骤1:reset saved-configuration 后输入y确认 步骤2:reboot后输入n否认再输入y确认 验证已经清空配置...
优选算法刷题笔记 2024.6.10-24.6.20
一、双指针算法(快慢指针,对撞指针) 艹,CSDN吞了我是十三题笔记!!! 二、滑动窗口(滑动窗口) 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通信总线再理解(中篇) 九. CAN总线标准十. CAN物理层十一. CAN数据链路层1)CAN的通信帧类型2)CAN的标准帧格式1. CAN ID2. 数据场 3)CAN总线仲裁 十二. CAN应用层1)CANopen2)…...
系统编程:互斥锁,条件变量
互斥锁 使用过程: 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日上午,蓝鹏测控公司全长直线度算法项目顺利通过多部门现场验收。该项目由公司技术部、开发部、生产部等多个部门共同参与,旨在提高直线度测量精度,满足高精度制造领域需…...
使用Python进行音频处理
通常会使用wave模块。但是,如果您想要处理其他类型的音频文件,或者需要更高级的音频处理功能,您可能需要安装第三方库,如pydub、soundfile、numpy等。 import wave # 读取WAV文件 with wave.open(input.wav, rb) as wav_file: …...
家有老人小孩,室内灰尘危害大!资深家政教你选对除尘空气净化器
哈喽,各位亲爱的朋友们!今天我们来聊聊每次大扫除时最让人头疼的问题——灰尘。你有没有发现,两天不打扫,桌子上就能积上一层灰;阳光一照,地板上的灰尘都在跳舞;整理被子的时候,空气…...
AI在创造与毁灭之间摇摆:音乐产业的机遇与挑战并存
AI到底在创造还是毁掉音乐? 最近一个月,轮番上线的音乐大模型,一举将素人生产音乐的门槛降到了最低,并掀起了音乐圈会不会被AI彻底颠覆的讨论。短暂的兴奋后,AI产品的版权归属于谁,创意产业要如何在AI的阴…...
Spring Boot集成 Spring Retry 实现容错重试机制并附源码
😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...
MDK-ARM 编译后 MAP 文件分析
本文配合 STM32 堆栈空间分布 食用更佳! 一图胜千言。。。...
antv g6实现系统拓扑图
1 背景 为例描述各个服务、redis、mysql等之间的联系及其健康状态,构建系统拓扑图,考虑 g6 更适合处理大量数据之间的关系,所以我们采用g6来绘制前端的图形。 g6提供的支持: 节点/边类型多样,同样支持自定义对于节点…...
因路径规划异常导致导航停止 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 的新架构(New Architecture)引入了一些新的组件和概念,旨在提高性能、增强灵活性和简化跨平台开发。主要组成部分包括: Fabric: Fabric Renderer: Fabric 是新的渲染引擎,它旨在取代现有的渲染引擎。与…...
Spring Security+Spring Boot实现登录认证以及权限认证
基本概念 “Authentication(认证)”是spring security框架中最重要的功能之一,所谓认证,就是对当前访问系统的用户给予一个合法的身份标识,用户只有通过认证才可以进入系统,在物理世界里,有点类似于“拿工卡刷门禁”的…...
5款堪称变态的AI神器,焊死在电脑上永不删除!
一 、AI视频合成工具——Runway: 第一款RunWay,你只需要轻轻一抹,视频中的元素就会被擦除,再来轻轻一抹,直接擦除,不喜欢这个人直接擦除,一点痕迹都看不出来。 除了视频擦除功能外,…...
Python和OpenCV图像分块之图像边长缩小比率是2
import cv2 import numpy as npimg cv2.imread("F:\\mytupian\\xihuduanqiao.jpg") # 低反光 cv2.imshow(image, img) # # 图像分块 # dst np.zeros(img.shape, img.dtype) ratio 2 #图像边长缩小比率是2,也就是一张图片被分割成四份 height, wi…...
C语言中的位域(bit-field)是什么,以及它的用途和优缺点
在C语言中,位域(bit-field)是一种特殊的数据结构,它允许在结构体(struct)中定义其成员所占用的位数,而不是使用整个字节或更大的内存空间。位域通常用于存储布尔值、状态标志、硬件控制位等&…...
从面试角度了解前端基础知识体系
目录 前端专业知识相关面试考察点 HTML 与 CSS Javascript 网络相关 浏览器相关 安全相关 算法与数据结构 计算机通用知识 前端项目经验相关面试考察点 前端框架与工具库 Node.js 与服务端 性能优化 前端工程化 开发效率提升 监控、灰度与发布 多人协作 结束语…...
【DKN: Deep Knowledge-Aware Network for News Recommendation】
DKN: Deep Knowledge-Aware Network for News Recommendation 摘要 在线新闻推荐系统旨在解决新闻信息爆炸的问题,为用户进行个性化推荐。 总体而言,新闻语言高度凝练,充满知识实体和常识。 然而,现有的方法并没有意识到这些外部…...
Linux管道与重定向
管道 是进程通信的方法之一,在Linux中用命令1|命令2的形式表示,将前一个命令的结果作为后续命令的参数进行输入,也有tee管道,可以进行多次筛选,即多次使用|过滤命令。 重定向 文件描述符FD Linux中输入输出分为三种…...
kotlin数组
1、kotlin中的数组与java数组比较: 2、创建 fun main() {// 值创建val a intArrayOf(1,2,3)// 表达式创建val b IntArray(3){println("it: ${it}")it1}println("a数组:${a.contentToString()}, 长度:${a.size}")prin…...
SpringSecurity实战入门——认证
项目代码 gson/spring-security-demo 简介 Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity来做安全框架。小项目有Shiro的比较多,因为相比…...
23种设计模式之桥接模式
桥接模式 1、定义 桥接模式:将抽象部分与它的实现部分解耦,使得两者都能独立变化 2、桥接模式结构 Abstraction(抽象类):它是用于定义抽象类的,通常是抽象类而不是接口,其中定义了一个Imple…...
常州免费网站建设/优化营商环境心得体会2023
题目描述:菜鸡在玩一个猜数字的游戏,但他无论如何都银不了,你能帮助他么 ** 0、下载附件,使用checksec查看保护情况和文件位数,尝试打开文件 ** 64位可执行文件,开启了canary,NX,…...
网站客服系统软件/哈尔滨seo网站管理
威纶通触摸屏怎么实现批量数据监视(三菱、西门子问题汇总)三菱常见问题解答1:通讯参数是8位数据位,偶校验,1位停止位,波特率19200,无帧头无帧尾,无协议模式,那么D8120多少?答:数据位࿱…...
手机制作网站的软件有哪些/网络营销服务公司
一、数据描述基本统计描述可以用来识别数据的性质,凸显哪些数据值应该视为噪声或离群点。中心趋势度量 :均值、中位数、众数;度量数据散步:极差、四分位数、方差、标准差和四分位数极差、变异系数;数据的基本统计描述的…...
网站空间服务器排名/手机网页链接制作
win7(xp) APMServ5.2.6 Apache启动失败,MYSQL启动失败 的解决办法1.APMServ程序所在路径不能含有汉字和空格。例子:D:\r\APMServ5.2.6\2.去掉如图的ssl :3.80端口被占用,关闭占用端口服务,或者改端口。4.如果发现上面的…...
贵阳市做网站的公司有哪些/软件开发培训班
文章目录电商业务流程电商常识SKU和SPU平台属性和销售属性电商系统表结构1,活动信息表(activity_info)2,活动规则表(activity_rule)3,活动商品关联表(activity_sku)4&…...
完全免费的网站源码/去除痘痘怎么有效果
最近看了不少关于用webpack做代码切割和持久缓存的文章,又因为这个被公司的大神虐了很久。 写一点收货,也不枉被虐了一番。 npm/yarn 这种方法网上关于webpack的文章里很常见,就是通过npm/yarn进行安装,然后由webpack直接打成模块…...