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技术&…...
二维码在设备点维一体化管理中的应用
随着科技发展,设备点维一体化管理体系应运而生,该管理体系的出现让设备维护保养变得更加高效精细化。 设备点维一体化管理体系以设备点检和维护保养为基础,通过日常、专业及精密点检,对点检测得的数据和设备给油脂保养情况进行统…...
如何安全使用R3nzSkin:5分钟快速上手指南
如何安全使用R3nzSkin:5分钟快速上手指南 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin 想在英雄联盟中免费体验所有皮肤,又担心账号安全?R3nzSkin这款…...
企业级应用如何通过Taotoken实现API调用的审计与安全管控
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业级应用如何通过Taotoken实现API调用的审计与安全管控 将大模型能力集成到企业内部系统,为业务流程带来智能化的同时…...
基于Ollama与Streamlit的本地大模型智能对话应用snowChat部署指南
1. 项目概述:一个基于本地大模型的智能对话应用最近在折腾本地部署的大语言模型,发现了一个挺有意思的项目,叫snowChat。这名字听起来就挺“冷”的,但功能却很“热”——它本质上是一个让你能在自己电脑上,用本地的大模…...
JDK 17文本块实战:告别繁琐拼接,拥抱多行字符串新写法
1. 为什么我们需要文本块? 如果你写过Java代码,肯定遇到过这样的场景:需要处理多行字符串,比如HTML模板、SQL语句或者JSON数据。在JDK 17之前,我们只能通过字符串拼接的方式来实现,代码看起来就像是一团乱麻…...
ESP32-S3 UF2 Bootloader修复指南:从原理到实战救砖
1. 项目概述:为什么ESP32-S3需要UF2 Bootloader?如果你玩过树莓派Pico或者一些Adafruit的开发板,可能会对那个插上USB后出现的U盘盘符有印象——直接把一个.uf2文件拖进去,固件就更新好了,简单得不像在搞嵌入式开发。这…...
【2026年5月16日最新】别再用Cursor了!这5款AI编程神器让我效率暴涨300%
2026年5月,AI编程工具迎来了史诗级更新潮。OpenAI发布GPT-5.5后,代码理解和工程重构能力达到历史最强;字节跳动Trae凭借全链路AI原生IDE和免费无限制政策迅速崛起;DeepSeek V4更是用极致算法效率撕开了算力铁幕 。作为一名每天和代…...
OpenClaw自动化配置实战:从入门到精通,打造高效工作流
1. 项目概述与核心价值最近在折腾开源自动化工具,发现了一个宝藏仓库:ShuyuZ1999/awesome-openclaw-configs。这个项目乍一看名字有点长,但核心价值非常明确——它是一个专门为开源自动化工具OpenClaw收集、整理和分享高质量配置文件的集合。…...
基于RAG架构构建私有知识库智能问答系统:从原理到部署实战
1. 项目概述:一个基于内容的智能对话机器人最近在GitHub上看到一个挺有意思的项目,叫mpaepper/content-chatbot。乍一看名字,你可能会觉得这又是一个基于大语言模型(LLM)的聊天机器人,市面上已经多如牛毛了…...
自制AVR ISP批量编程器:从ZIF插座到AVRDUDE一键烧录全攻略
1. 项目概述:为什么你需要一个批量编程器?如果你玩过Arduino或者自己做过一些基于AVR单片机的小项目,那么对“烧录程序”这个步骤一定不陌生。通常,我们是用一根USB线,或者一个USBasp、USBtinyISP这样的小编程器&#…...
Arduino Audio Tools终极指南:从音频新手到专业开发者的完整解决方案
Arduino Audio Tools终极指南:从音频新手到专业开发者的完整解决方案 【免费下载链接】arduino-audio-tools Arduino Audio Tools (a powerful Audio library not only for Arduino) 项目地址: https://gitcode.com/gh_mirrors/ar/arduino-audio-tools 在嵌入…...
