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

《白话C++》第9章 泛型,Page842~844 9.4.2 AutoPtr

源起:

C++编程中,最容易出的问题之一,就是内存泄露,而new一个对象,却忘了delete它,则是造成内存泄露的主要原因之一

例子一:

void foo()
{XXXObject* xo = new XXXObject;if(!xo->DoSomething())//do something出错了return;//返回(可是,糟糕,忘了delete xo呢)try{xo->DoAnotherThing();}catch(...)//出异常了...{return false; //又忘了delete xo了。}delete xo;return;
}

函数最后是释放xo,可是在DoSomething和DoAnotherThing不成功后,忘了释放xo,直接return了。

例子二:

XXXObject* CreateXXXFromFile(char const* filename)
{std::ifstream ifs(filename);int i;std::string s;ifs >> i;std::getline(ifs, s);XXXObject* xo = new XXXObject(i, s);xo->init();return xo;
}

C++编程箴言之一:“谁创建,谁释放”。

“CreateXXX”这类函数,经常被称为“工厂函数”。在特定的业务逻辑下,创建一个对象,需要像车间流水线一样先准备一些零件(例中的i和s),最后再调用构造函数产生一个对象。

问题出在使用者身上:

void foo()
{XXXObject* xo = CreateXXXFromFile("d:\\material\1.dat");xo->DoSomething();return;
}

更有甚者:

void foo()
{/*调用者根本没有处理CreateXXXFromFile()返回的指针,放任它占用内存不释放,(当然,这样使用函数,通常逻辑上也有错误)*/CreateXXXFromFile("d:\\material\\1.dat");
}

作为CreateXXXFromFile的作者,有没有办法既能够方式一个new出来的对象,又能够在调用者忘记释放它的返回值(哪怕是干脆没有提供变量用以“hold”住返回值)时,自动干掉函数内部创建的那个对象呢?我们已经知道,可以使用shared_ptr<T>,但如果假装不知道呢?

基本解决思路

C++的两个特性:

一是内存占用至少分成两种:栈内存和堆内存,堆内存需要手工释放,栈内存却能在其作用域结构之后,自动释放;

二是C++对象会在释放时,调用析构函数。

结合这连个特性,可以将“堆”内存(new出来的内存是堆内存的一种)在生命周期管理行为,模拟成“栈”内存方式。

先看第一个版本,用作原理演示:

struct AutoPtr
{AutoPtr(){this->_ptr = new int;}~AutoPtr(){cout << "调用析构,删除指针" << endl;delete this->_ptr;}int* _ptr;
};

AutoPtr在构造时,创建一个整数指针,在析构时,删除它。这一原理,它已经可以投入使用,做个对比:

原始版本(裸指针)AutoPtr版本一
void foo_1()
{
    cout << "foo_1使用裸指针" << endl;
    int * ptr = new int;
    * ptr = 100;
    cout << * ptr << endl;
    delete ptr; //手工释放
}
void foo_2()
{
    cout << "foo_2使用AutoPtr" << endl;
    AutoPtr ap;
    *(ap._ptr) = 100;
    cout << *(ap._ptr) << endl;
}

原始版本

AutoPtr版本一

foo_2函数一结束,栈变量ap就会自动释放,释放是调用析构,析构函数负责释放_ptr。

AutoPtr的第一个缺陷:

它固定只用于int指针。这问题好解决,上模板呀:

template <typename T>
struct AutoPtr
{AutoPtr(){this->_ptr = new T;}~AutoPtr(){delete this->_ptr;}T* _ptr;
};

课堂作业:AutoPtr模板版本应用

67行,sap死亡时,调用析构函数,会删除_ptr一次

88行,又删除_ptr一次,所以内存释放两次

相关文章:

《白话C++》第9章 泛型,Page842~844 9.4.2 AutoPtr

源起&#xff1a; C编程中&#xff0c;最容易出的问题之一&#xff0c;就是内存泄露&#xff0c;而new一个对象&#xff0c;却忘了delete它&#xff0c;则是造成内存泄露的主要原因之一 例子一&#xff1a; void foo() {XXXObject* xo new XXXObject;if(!xo->DoSomethin…...

服务流控(Sentinel)

引入依赖 <!-- 必须的 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><!-- sentinel 核心库 --> <dependency><groupId>com.ali…...

点亮代码之灯,程序员的夜与电脑

在科技的海洋里&#xff0c;程序员是那些驾驶着代码船只&#xff0c;穿梭于虚拟世界的探险家。他们手中的键盘是航行的舵&#xff0c;而那台始终不愿关闭的电脑&#xff0c;便是他们眼中永不熄灭的灯塔。有人说&#xff0c;程序员不喜欢关电脑&#xff0c;这究竟是为什么呢&…...

ClickHouse--07--Integration 系列表引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Integration 系列表引擎1 HDFS1.1 语法1.2 示例&#xff1a; 2 MySQL2.1 语法2.2 示例&#xff1a; 3 Kafka3.1 语法3.2 示例&#xff1a;3.3 数据持久化方法 Integ…...

前端架构: 脚手架框架之yargs的11种基础核心特性的应用教程

脚手架框架之yargs的基础核心特性与应用 1 &#xff09;概述 yargs 是脚手架当中使用量非常大的一个框架进入它的npm官网: https://www.npmjs.com/package/yargs 目前版本: 17.7.2Weekly Downloads: 71,574,188 (动态数据)最近更新&#xff1a;last month (github)说明这是一个…...

MySQL性能调优篇(6)-主从复制的配置与管理

MySQL数据库主从复制是一种常用的数据复制和高可用性解决方案。它允许将一个MySQL主服务器上的数据自动复制到多个从服务器上&#xff0c;从而提供了数据冗余备份、读写分离等优势。本文将详细介绍MySQL数据库主从复制的配置与管理。 1. 原理概述 MySQL主从复制是基于二进制日…...

Linux第49步_移植ST公司的linux内核第1步_获取linux源码

已知ST公司的linux源码路径&#xff1a; /home/zgq/linux/atk-mp1/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0 1、创建“my_linux”目录 打开第1个终端 输入“ls回车” 输入“cd linux/回车”&#xff0c;切换…...

怎样学习Windows下命令行编写

第一&#xff1a;Windows下命令行指的是cmd和powershell命令行编写 第二&#xff1a;必须要用好help或/?命令&#xff0c;这个命令是最基本的也是最常用的命令列表和语法查看命令 第三&#xff1a;cmd命令使用help查看命令列表或“一串带参数的命令 /?"&#xff08;不…...

数据结构第十六天(二叉树层序遍历/广度优先搜索(BFS)/队列使用)

目录 前言 概述 接口 源码 测试函数 运行结果 往期精彩内容 前言 从前的日色变得慢&#xff0c;车&#xff0c;马&#xff0c;邮件都慢&#xff0c;一生,只够爱一个人。 概述 二叉树的层序遍历可以使用广度优先搜索&#xff08;BFS&#xff09;来实现。具体步骤如下&…...

6.s081 学习实验记录(八)Networking

文章目录 network driver network driver //TODO...

图解贝塞尔曲线生成原理

贝塞尔曲线是一种在计算机图形学中广泛使用的参数曲线&#xff0c;主要用于二维图形应用程序中。它是由法国工程师皮埃尔贝塞尔在1962年提出的&#xff0c;主要用于汽车车身设计。贝塞尔曲线的主要特点是&#xff0c;只要确定了控制点&#xff0c;就可以生成一条平滑的曲线。 …...

租房招聘|在线租房和招聘平台|基于Springboot的在线租房和招聘平台设计与实现(源码+数据库+文档)

在线租房和招聘平台目录 目录 基于Springboot的在线租房和招聘平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、房屋管理 2、招聘管理 3、平台资讯管理 4、平台资讯类型管理 四、数据库设计 1、实体ER图 六、论文参考 七、最新计算机毕设选题推荐 八、源…...

简单试验:用Excel进行爬虫

文章目录 Excel的版本具体操作实例从网站上爬取工商银行的汇率Excel的版本 office 2016,2019,365这几个版本都可以 具体操作 #mermaid-svg-NlIVMivGoJbdyWW0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-NlIVMi…...

SQL 精讲-MySql 常用函数,MySQL语句精讲和举例

FORMAT(数值,保留位数) 四舍五入 SELECT *,FORMAT(score/3,2) from studentROUND(数值,保留位数) 四舍五入 SELECT ROUND(score/3,2) from studentCONCAT(字符串 1,字符串 2) 字符串拼接 SELECT CONCAT(customer_name, (,address,)) from mt_customerLEFT(字符串,长度) 截取…...

nlp中如何数据增强

在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;数据增强是一种常用的技术&#xff0c;旨在通过对原始文本进行一系列变换和扩充&#xff0c;生成更多多样化的训练数据。这有助于提高模型的泛化能力和鲁棒性。下面是一些常见的数据增强方法在NLP中的应用&#xff1a;…...

python:xml.etree,用 xmltodict 转换为json数据,生成jstree所需的文件

请参阅&#xff1a;java : pdfbox 读取 PDF文件内书签 或者 python&#xff1a;从PDF中提取目录 请注意&#xff1a;书的目录.txt 编码&#xff1a;UTF-8&#xff0c;推荐用 Notepad 转换编码。 xml 是 python 标准库&#xff0c;在 D:\Python39\Lib\xml\etree pip install …...

C#log4net日志保存到Sqlserver数据库表(16)

要将log4net的日志保存到SQL Server数据库表中&#xff0c;你需要配置log4net使用一个数据库追加器&#xff08;appender&#xff09;&#xff0c;通常是AdoNetAppender。以下是一个示例配置&#xff0c;展示如何将log4net的日志输出配置为写入SQL Server数据库表。 首先&…...

SpringCloud-Nacos集群搭建

本文详细介绍了如何在SpringCloud环境中搭建Nacos集群&#xff0c;为读者提供了一份清晰而详尽的指南。通过逐步演示每个关键步骤&#xff0c;包括安装、配置以及Nginx的负载均衡设置&#xff0c;读者能够轻松理解并操作整个搭建过程。 一、Nacos集群示意图 Nacos&#xff0…...

第十五届蓝桥杯全国软件和信息技术专业人才大赛个人赛(软件赛)软件测试组竞赛规则及说明

第十五届蓝桥杯全国软件和信息技术专业人才大赛个人赛 (软件赛)软件测试组竞赛规则及说明 目录...

【算法与数据结构】496、503、LeetCode下一个更大元素I II

文章目录 一、496、下一个更大元素 I二、503、下一个更大元素II三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、496、下一个更大元素 I 思路分析&#xff1a;本题思路和【算法与数据结构】739、LeetCode每日温度类似…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

边缘计算网关提升水产养殖尾水处理的远程运维效率

一、项目背景 随着水产养殖行业的快速发展&#xff0c;养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下&#xff0c;而且难以实现精准监控和管理。为了提升尾水处理的效果和效率&#xff0c;同时降低人力成本&#xff0c;某大型水产养殖企业决定…...

HTML版英语学习系统

HTML版英语学习系统 这是一个完全免费、无需安装、功能完整的英语学习工具&#xff0c;使用HTML CSS JavaScript实现。 功能 文本朗读练习 - 输入英文文章&#xff0c;系统朗读帮助练习听力和发音&#xff0c;适合跟读练习&#xff0c;模仿学习&#xff1b;实时词典查询 - 双…...