C++ 使用动态内存创建一个类
使用动态内存的一个常见原因是允许多个对象共享相同的状态。
例如,假定我们希望定义一个名为
Blob的类,保存一组元素。与容器不同,我们希望Blob对象的不同拷贝之间共享相同的元素。即,当我们拷贝一个Blob时,原Blob对象及其拷贝应该引用相同的底层元素。现在我们先定义一个管理string的类,此版本命名为StrBlob。
定义 StrBlob类
实现一个新的集合类型的最简单方法是使用某个标准库容器来管理元素。采用这种方法,我们可以借助标准库类型来管理元素所使用的内存空间。在本例中,我们将使用vector来保存元素。
但是,我们不能在一个Blob对象内直接保存vector,因为一个对象的成员在对象销毁时也会被销毁。例如,
- 假定
b1和b2是两个Blob对象,共享相同的vector。 - 如果此
vector保存在其中一个Blob中——例如b2中,那么当b2离开作用域时,此vector也将被销毁,也就是说其中的元素都将不复存在。为了保证vector中的元素继续存在,我们将vector保存在动态内存中。
为了实现我们所希望的数据共享,我们为每个StrBlob设置一个shared_ptr来管理动态分配的 vector。此 shared_ptr的成员将记录有多少个StrBlob 共享相同的vector,并在vector的最后一个使用者被销毁时释放vector。
我们还需要确定这个类应该提供什么操作。当前,我们将实现一个vector操作的小的子集。我们会修改访问元素的操作(如 front和 back): 在我们的类中,如果用户试图访问不存在的元素,这些操作会抛出一个异常。
我们的类有一个默认构造函数和一个构造函数,接受单一的 initializer_list<string>类型参数。此构造函数可以接受一个初始化器的花括号列表。
initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。在进行函数调用的时候需要使用花括号将所有的参数括起来。
class StrBlob{
public:typedef std::vector<std::string>::size_type size_type;StrBlob();StrBlob(std::initializer_list<std::string> il);size_type size() const { return data->size(); }bool empty() const { return data->empty(); }//添加和删除元素void push_back(const std::string &t){ data->push_back(t); }void pop_back();//元素访问std::string& front();std::string& back();private:std::shared_ptr<std::vector<std::string>> data;//如果data[i]不合法,抛出一个异常void check(size_type i, const std::string &msg) const;
};
在此类中,我们实现了size、empty和 push_back成员。这些成员通过指向底层vector的 data成员来完成它们的工作。例如,对一个 StrBlob对象调用size()会调用data->size(),依此类推。
StrBlob构造函数
两个构造函数都使用初始化列表来初始化其data成员,令它指向一个动态分配的vector。默认构造函数分配一个空vector:
StrBlob::StrBlob() : data(make_shared<vector<string>>()){ }
StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }
接受一个initializer_list的构造函数将其参数传递给对应的vector构造函数。此构造函数通过拷贝列表中的值来初始化vector的元素。
元素访问成员函数
pop_back、front和 back操作访问vector中的元素。这些操作在试图访问元素之前必须检查元素是否存在。由于这些成员函数需要做相同的检查操作,我们为StrBlob定义了一个名为check的private工具函数,它检查一个给定索引是否在合法范围内。除了索引,check还接受一个string参数,它会将此参数传递给异常处理程序,这个string描述了错误内容:
void StrBlob::check(size_type i, const string &msg) const
{if(i >= data->size())throw out_of_range(msg);
}
pop_back和元素访问成员函数首先调用check。如果check成功,这些成员函数继续利用底层vector的操作来完成自己的工作:
string& StrBlob::front()
{//如果vector为空,check会抛出一个异常check(0, "front on empty StrBlob");return data->front();
}
string& StrBlob::back()
{check(0, "back on empty StrBlob");return data->back();
}
void StrBlob::pop_back()
{check(0, "pop_back on empty StrBlob");data->pop_back();
}
StrBlob 的拷贝、赋值和销毁
StrBlob使用默认版本的拷贝、赋值和销毁成员函数来对此类型的对象进行这些操作。默认情况下,这些操作拷贝、赋值和销毁类的数据成员。
我们的StrBlob类只有一个数据成员,它是shared_ptr类型。因此,当我们拷贝、赋值或销毁一个 StrBlob对象时,它的shared_ptr成员会被拷贝、赋值或销毁。
- 拷贝一个
shared_ptr会递增其引用计数; - 将一个
shared_ptr赋予另一个shared_ptr会递增赋值号右侧shared_ptr的引用计数,而递减左侧shared_ptr的引用计数。 - 如果一个
shared_ptr的引用计数变为0,它所指向的对象会被自动销毁。因此,对于由StrBlob构造函数分配的vector,当最后一个指向它的StrBlob对象被销毁时,它会随之被自动销毁。
注:仅供学习参考,如有不足,欢迎指正!
相关文章:
C++ 使用动态内存创建一个类
使用动态内存的一个常见原因是允许多个对象共享相同的状态。 例如,假定我们希望定义一个名为Blob 的类,保存一组元素。与容器不同,我们希望Blob对象的不同拷贝之间共享相同的元素。即,当我们拷贝一个Blob时,原Blob对象…...
2023年华中杯选题人数公布
2023年华中杯选题人数公布 经过一晚上代码的编写,论文的写作,C题完整版论文已经发布, 注:蓝色字体为说明备注解释字体,不能出现在大家的论文里。黑色字体为论文部分,大家可以根据红色字体的注记进行摘抄。…...
【黑马旅游案例记录(结合ES)】
黑马旅游案例记录 11.9.黑马旅游案例11.9.1.酒店搜索和分页11.9.1.1.需求分析11.9.1.2.定义实体类11.9.1.3.定义controller11.9.1.4.实现搜索业务 11.9.2.酒店结果过滤11.9.2.1.需求分析11.9.2.2.修改实体类11.9.2.3.修改搜索业务 11.9.3.我周边的酒店11.9.3.1.需求分析11.9.3.…...
基于 A* 搜索算法来优化无线传感器节点网络的平均电池寿命(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨💻4 Matlab代码 💥1 概述 A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法。它有较好的性能和准确度。本文…...
三款自研AI应用引领未来,重塑行业新风尚
在这个科技日新月异的时代,AI技术已经渗透到我们生活的方方面面。今天,我们将向您推荐三款领域独具特色的AI应用,它们分别是AI律师、AI小红书文案提示词、以及AI Midjourney提示词。这些应用都具有独特的内涵,让我们一起走进这些智…...
Kafka的命令行操作
一、topic命令 下面Windows命令需要把cmd路径切换到bin/windows下。 而Linux命令只需要在控制台切换到bin目录下即可。 下面都以Windows下的操作为例,在Linux下也是一样的。 1.1 查看主题命令的参数 kafka-topics.bat # Windows kafka-topics.sh # Linux输…...
递归,回溯,分治(C++刷题笔记)
递归,回溯,分治(C刷题笔记) 78. 子集 力扣 预备知识 nums[][1,2,3],先将子集[1],[1,2],[1,2,3]打印 #include <bits/stdc.h>using namespace std;int main() {vector<int>nums;for (int i1;i<3;i){nums.push_…...
CentOS 7.6更改yum源
使用字符串替换 我这里的操作参考了https://baijiahao.baidu.com/s?id1708418392526536542&wfrspider&forpc这篇文章,https://mirrors.tuna.tsinghua.edu.cn/help/centos/是清华大学官网教程。 /etc/yum.repos.d/CentOS-Base.repo文件如下: #…...
三、进度管理
3、 [单选] 一个项目实施团队需要满足一份非常严格的进度计划。相对于已完成的事项,这样会导致正在进行的工作超过负荷。为了解决这个问题,项目经理需要获得额外的资源。项目经理应该向发起人提供什么理由来支持追加资源的请求? A project im…...
基于LEACH和HEED的WSN路由协议研究与改进(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨💻4 Matlab代码 💥1 概述 无线传感器网络是不断发展的传感技术之一,也用于执行不同的任务。这些类型的网络在许多领域都是有益的,…...
ChatGPT镜像站收集【Free ChatGPT】(一)
文章目录 Free ChatGPT Site ListLast synced:BeiJingT 2023-04-18妙站站点列表Free ChatGPT Site List 这儿收集了一些免费好用的ChatGPT镜像站点 ⭐:使用不受限🔑:需要进行登录⛔:有限地使用次数后需提供key或进行充值❓ :未测试,未进行标注也为未测试Last synced:BeiJin…...
PHP面试宝典之Mysql数据库基础篇
字符类型: tinyint(4):占1个字节,4代表字段值长度,用0填充,搭配zero fill使用 有符号:取值范围 负128 ~ 正127; 无符号:取值范围 0 ~ 255; 默认无…...
4月记录总结
4/24 1.GBK12、16、24是指什么 GBK12、GBK16、GBK24是指不同的字体点阵大小,也就是字体的显示大小。在GBK编码中,一个汉字通常是由多个点阵组成的,其中点阵的大小就是字体的点阵大小。具体来说: GBK12:指每个汉字由12…...
每日学术速递4.29
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.LG 1.A Cookbook of Self-Supervised Learning 标题:自监督学习食谱 作者:Randall Balestriero, Mark Ibrahim, Vlad Sobal, Ari Morcos, Shashank Shekhar, Tom…...
整数在内存中的存储:原码、反码、补码 大小端字节序
本篇博客会讲解整数在内存中的存储形式,以及整数二进制的3种表示形式:原码、反码、补码,还有大小端的相关知识点。相信读完本篇博客,大家对内存的了解会上一个台阶。 注意:本篇博客讨论的是整数在内存中的存储&#x…...
【方法】 如何批量将RAR或其他压缩格式转换成ZIP?
压缩文件的格式有很多种,比如RAR、ZIP、7-Zip、CAB、ARJ、ACE、TAR、BZ2等等。因为需求不同,或者不同平台对上传的压缩包格式要求不同,我们往往需要把压缩文件进行格式转换,那压缩文件不同格式之间如何进行转换呢? 如…...
《道德经》
《道德经》是春秋时期老子(李耳)的哲学作品,又称《道德真经》、《老子》、《五千言》、《老子五千文》,是中国古代先秦诸子分家前的一部著作,是道家哲学思想的重要来源。 道德经分上下两篇,原文上篇《德经…...
ABI Research产业研究:ZiFiSense如何革新物流货物及运输包装追踪
“文章源自前沿科技研究机构ABI Research产业研究,重点介绍了ZETA LPWA协议开发公司纵行科技在业务发展、M-FSK调制技术以及ZETag云标签系列产品在物流货物追踪与包装管理等方面的应用分析,还分享了纵行科技ZETA技术在商业市场和生态系统方面的发展情况。…...
家乡特色推荐系统~java~mysql
摘 要 在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括家乡特色推荐的网络应用,在外国家乡特色推荐系统已经是很普遍的方式,不过国内的管理网站可能还处于起步阶段。家乡特色推荐系统采用java技术&…...
二维码在设备点维一体化管理中的应用
随着科技发展,设备点维一体化管理体系应运而生,该管理体系的出现让设备维护保养变得更加高效精细化。 设备点维一体化管理体系以设备点检和维护保养为基础,通过日常、专业及精密点检,对点检测得的数据和设备给油脂保养情况进行统…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
