智能指针——浅析
智能指针
本人不才,只能将智能指针介绍一下,无法结合线程进行深入探索
介绍及作用
在异常产生进行跳转时,通过栈帧回收进行内存释放,防止内存泄漏
基于RAII思想可以创建出只能指针
RAII(Resource Acquisition Is Initialization)——是一种利用对象控制空间生命周期的技术
这种技术好处就在于可以自动化的释放资源
智能指针——使用如指针,支持->和*,*针对内置数据类型,->针对自定义数据类型
先介绍一个对象管理一份资源
auto_ptr
template<class T>class auto_ptr{// auto_ptr 会产生指针悬空的情况,在进行解引用的时候很危险public:auto_ptr(T* p=nullptr) :_ptr(p) {}~auto_ptr(){puts("~auto_ptr()");delete _ptr;}auto_ptr(auto_ptr<T>& p){_ptr = p._ptr;p._ptr = nullptr;}auto_ptr<T>& operator=(auto_ptr<T>& p){// 因为是一个对象管理一份资源,比较的时候也可以使用this!=&pif (_ptr != p._ptr){if (_ptr) delete _ptr;_ptr = p._ptr;p._ptr = nullptr;}return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
auto_ptr会在赋值的时候将资源进行转移,并将自己置为nullptr,从而造成指针悬空的问题
unique_ptr
template<class T>class unique_ptr{// 在auto_ptr的基础上进行优化,防拷贝public:unique_ptr(T* p = nullptr) :_ptr(p) {}~unique_ptr(){puts("~auto_ptr()");delete _ptr;}unique_ptr(const unique_ptr<T>& p) = delete;unique_ptr& operator=(const unique_ptr<T>& p) = delete;T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:// unique_ptr(const unique_ptr<T>& p);// unique_ptr& operator=(const unique_ptr<T>& p);T* _ptr;};
只是为了解决拷贝带来的指针悬空的问题——
禁用拷贝构造和赋值重载
有两种方式达到禁用拷贝构造和赋值重载
- 将拷贝构造和赋值重载
定义成private- 由于
C++11扩展了delete的功能,可以在public中对两个函数使用delete关键字修饰
多个指针同时享有一份资源
shared_ptr
使用一个计数指针进行计数
我的代码写成这个样子是因为考虑到可能只声明指针但是没有赋值的情况,所以就需要对指针位nullptr的情况进行特殊判断
struct ListNode
{int val;bit::shared_ptr<ListNode> next;bit::shared_ptr<ListNode> prev;~ListNode(){cout << "~ListNode()" << endl;}
};template<class T>class shared_ptr {// 删除器就是为了解决:释放数组,不是new出来的指针public:shared_ptr(T* p = nullptr) :_ptr(p), _count(new int(0)) {}template<class D>shared_ptr(T* p,D del):_ptr(p),_count(new int(1)),_del(del){if (p) (*_count)++;}~shared_ptr(){if (_ptr){//printf("~shared_ptr() -> %p\n", _ptr);if (--(*_count) == 0){delete _count;}delete _ptr;}if (_ptr == nullptr) delete _count;}shared_ptr(const shared_ptr<T>& p){if (_ptr && _ptr != p._ptr){if (--(*_count) == 0) _count = p._count;(*_count)++;_ptr = p._ptr;}else{// nullptr / 有值相等_ptr = p._ptr;_count = p._count;//*_count++; // ++优先级大于*,最好不要写这种代码(*_count)++;}}shared_ptr& operator=(const shared_ptr<T>& p){if (_ptr && _ptr != p._ptr){if (--(*_count) == 0) _count = p._count;(*_count)++;_ptr = p._ptr;}else{// nullptr / 有值相等_ptr = p._ptr;_count = p._count;(*_count)++;}return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}int use_count() const {return *_count;}T* get() const{return _ptr;}private:T* _ptr;int* _count;// 引入计数指针function<void(T*)> _del = [](T* p) {delete p; };};

这里会产生循环引用的问题

为了解决这个问题有了weak_ptr
weak_ptr
weak_ptr只进行引用不进行计数
struct ListNode
{int val;bit::weak_ptr<ListNode> next;bit::weak_ptr<ListNode> prev;~ListNode(){cout << "~ListNode()" << endl;}
};template<class T>class weak_ptr{// 不增加引用计数public:weak_ptr() :_ptr(nullptr) {}~weak_ptr(){//printf("~shared_ptr() -> %p\n", _ptr);}weak_ptr(const shared_ptr<T>& p){_ptr = p.get();}weak_ptr& operator=(const shared_ptr<T>& p){_ptr = p.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

使用包装器进行释放
这里还有一个问题——如何根据空间开的个数进行释放呢,数组和指针释放的方式是不一样的
也就是在share_ptr看不懂的版本
template<class T>
struct Del
{void operator()(T* ptr){delete[] ptr;}
};template<class T>class shared_ptr {// 删除器就是为了解决:释放数组,不是new出来的指针public:shared_ptr(T* p = nullptr) :_ptr(p), _count(new int(0)) {}template<class D>shared_ptr(T* p,D del):_ptr(p),_count(new int(1)),_del(del){if (p) (*_count)++;}~shared_ptr(){if (_ptr){//printf("~shared_ptr() -> %p\n", _ptr);if (--(*_count) == 0){delete _count;}delete _ptr;}if (_ptr == nullptr) delete _count;}shared_ptr(const shared_ptr<T>& p){if (_ptr && _ptr != p._ptr){if (--(*_count) == 0) _count = p._count;(*_count)++;_ptr = p._ptr;}else{// nullptr / 有值相等_ptr = p._ptr;_count = p._count;//*_count++; // ++优先级大于*,最好不要写这种代码(*_count)++;}}shared_ptr& operator=(const shared_ptr<T>& p){if (_ptr && _ptr != p._ptr){if (--(*_count) == 0) _count = p._count;(*_count)++;_ptr = p._ptr;}else{// nullptr / 有值相等_ptr = p._ptr;_count = p._count;(*_count)++;}return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}int use_count() const {return *_count;}T* get() const{return _ptr;}private:T* _ptr;int* _count;// 引入计数指针function<void(T*)> _del = [](T* p) {delete p; };};
仿函数,函数指针,lambda可以使用包装器——不论使用哪一种,实现的目的就是为了释放数组
他的类型一定是void(*T)
为什么需要在声明的时候就给默认到lambda——如果在这个指针是拷贝构造生成的,那还得进行包装器拷贝,同样在赋值重载的地方也需要同样的操作,还不如声明的时候给默认值
相关文章:
智能指针——浅析
智能指针 本人不才,只能将智能指针介绍一下,无法结合线程进行深入探索 介绍及作用 在异常产生进行跳转时,通过栈帧回收进行内存释放,防止内存泄漏 基于RAII思想可以创建出只能指针 RAII(Resource Acquisition Is Initializatio…...
JAVA后端上传图片至企微临时素材
1.使用场景 在使用企业微信API接口中,往往开发者需要使用自定义的资源,比如发送本地图片消息,设置通讯录自定义头像等。 为了实现同一资源文件,一次上传可以多次使用,这里提供了素材管理接口:以media_id来…...
MySQL-----初识
一 SQL的基本概述 基本概述 ▶SQL全称: Structured Query Language,是结构化查询语言,用于访问和处理数据库的标准的计算机语言。SQL语言1974年由Boyce和Chamberlin提出,并首先在IBM公司研制的关系数据库系统SystemR上实现。 ▶美国国家标…...
[基础IO]文件描述符{重定向/perror/磁盘结构/inode/软硬链接}
文章目录 1. 再识重定向2.浅谈perror()3.初始文件系统4.软硬链接 1. 再识重定向 图解./sf > file.txt 2>&1 1中内容拷贝给2 使得2指向file 再学一个 把file的内容传给cat cat拿到后再给file2 2.浅谈perror() open()接口调用失败返回-1,并且错误码errno被适当的设置,…...
NAS系统折腾记 – Emby搭建家庭多媒体服务器
Emby简介 Emby是一款优秀的媒体服务器软件,致力于为用户提供丰富的多媒体体验。通过Emby,您可以方便地在家庭内的各种设备上观看您喜爱的电影、电视剧和其他视频内容。而且,Emby还具备强大的媒体管理功能,让您的影视资源井然有序…...
#从零开始# 在深度学习环境中,如何用 pycharm配置使用 pipenv 虚拟环境
为Python项目创建虚拟环境 在深度学习环境和一般python环境中安装pipenv基本一致,只需要确认好pipenv指定的python版本即可,安装pipenv前,可以通过python --version来确认安装版本 快捷键:crtl alt S 查看interpreter,查看所有…...
Cmake编译Opencv3.3.1遇到有些文件无法下载的错误解决:
前言: 对于,opencv有些配置文件错误并未致命,所以,有错误也不影响后续的编译:但是,后引用如果要用,在回过头来还是要解决的。 问题表述: 比如,有些文件下载的错误&am…...
Python基础知识:Python序列以及序列的索引、切片、相乘和相加
索引 索引就是序列中的每个元素所在的位置,可以通过从左往右的正数索引,也可以通过从右往左的负数索引。 从左往右的正数索引:在python序列中,第一个元素的索引值为0,第二个元素的索引值为1,以此类推&…...
回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测
回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测 目录 回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-GRU【24年新算法】冠豪猪优化…...
开源项目TARZAN-NAV | 基于springboot的现代化导航网站系统
TARZAN-NAV 导航网站 一个基于 Spring Boot、MyBatis-Plus、h2database、ehcache、Docker、websocket等技术栈实现的导航网站系统,采用主流的互联网技术架构、全新的UI设计、支持一键源码部署,拥有完整的仪表板、导航管理,用户管理、评论管理…...
SQL查询数据之多表(关联)查询
数据表: 关联查询主要分为:(inner join)交叉关联、(left join)左关联、(right join)右关联 (inner join)交叉关联: 定义:࿰…...
常见的web前端开发框架介绍
Web前端开发框架是为了简化网页设计和开发的流程而创建的工具集。它们提供了预定义的组件、工具和库,帮助开发者快速构建交互式的用户界面。以下是一些常见的Web前端开发框架,以及它们的原理、基础技术和应用场景的介绍: 1. React **…...
CSS 选择器与相关规则详解
CSS(Cascading Style Sheets)的选择器是网页样式设计中至关重要的工具,它们允许开发者精确地定位并应用样式到HTML文档中的元素。下面将逐一介绍几种主要的选择器类型,以及相关的注释和规则。 1. 类选择器 (Class Selector) 类选…...
基于springboot的宠物店系统的设计与实现
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…...
Llama2大模型开源,大模型的Android时代来了?
就昨天凌晨,微软和Meta宣布Llama2大模型开源且进一步放开商用,一下朋友圈刷屏。要知道,开源界最强大的模型就是过去Meta开源的Llama,而现在Llama2更强大,又开放商用,更有微软大模型霸主企业撑腰(微软既投资大模型界的IOS——ChatGPT,又联合发布大模型的Android——Llam…...
取出list中指定数量数据操作,操作完了删除这些数据
直接看代码吧,有注释 package com.ep.crm.task;import java.util.ArrayList; import java.util.List; import java.util.Random;public class Test {public static void main(String[] args) {List<String> list new ArrayList<String>();// 生成随机整数Random …...
Cocos XR的WebBox实现流程
1. 正常3D场景下的webview 1.1 组件角色 Cocos Creator正常3D场景下只有在UI组件才支持webview,即作为下图中的UI Nodes(Canvas Node)的子节点,和3D组件是隔离开的,不能显示在3D空间中,UI Nodes(Canvas Node)是一个平面内的矩形…...
netstat是一个常用的网络工具,用于显示和分析网络连接、路由表以及网络接口等信息。
netstat 是一个常用的网络工具,用于显示和分析网络连接、路由表以及网络接口等信息。 它可以提供关于网络活动的实时统计数据,包括正在监听的端口、已建立的连接、网络接口的状态等。 使用 netstat 命令可以列出当前系统中的网络连接情况。以下是一些常…...
【Linux】linux权限
linux权限 一,Linux权限的概念二,Linux权限管理1.文件访问者分类2.文件类型和访问权限3.文件权限值的表示方法4.文件访问权限的设置 三,目录的权限四,粘滞位五,权限掩码1.什么是权限掩码2.权限掩码的计算 一࿰…...
XUbuntu22.04之如何创建、切换多个工作区(二百零九)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
