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

智能指针——浅析

智能指针

本人不才,只能将智能指针介绍一下,无法结合线程进行深入探索

介绍及作用

在异常产生进行跳转时,通过栈帧回收进行内存释放,防止内存泄漏
基于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;};

只是为了解决拷贝带来的指针悬空的问题——禁用拷贝构造和赋值重载
两种方式达到禁用拷贝构造和赋值重载

  1. 将拷贝构造和赋值重载定义成private
  2. 由于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——如果在这个指针是拷贝构造生成的,那还得进行包装器拷贝,同样在赋值重载的地方也需要同样的操作,还不如声明的时候给默认值

相关文章:

智能指针——浅析

智能指针 本人不才&#xff0c;只能将智能指针介绍一下&#xff0c;无法结合线程进行深入探索 介绍及作用 在异常产生进行跳转时&#xff0c;通过栈帧回收进行内存释放&#xff0c;防止内存泄漏 基于RAII思想可以创建出只能指针 RAII(Resource Acquisition Is Initializatio…...

JAVA后端上传图片至企微临时素材

1.使用场景 在使用企业微信API接口中&#xff0c;往往开发者需要使用自定义的资源&#xff0c;比如发送本地图片消息&#xff0c;设置通讯录自定义头像等。 为了实现同一资源文件&#xff0c;一次上传可以多次使用&#xff0c;这里提供了素材管理接口&#xff1a;以media_id来…...

MySQL-----初识

一 SQL的基本概述 基本概述 ▶SQL全称: Structured Query Language&#xff0c;是结构化查询语言&#xff0c;用于访问和处理数据库的标准的计算机语言。SQL语言1974年由Boyce和Chamberlin提出&#xff0c;并首先在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是一款优秀的媒体服务器软件&#xff0c;致力于为用户提供丰富的多媒体体验。通过Emby&#xff0c;您可以方便地在家庭内的各种设备上观看您喜爱的电影、电视剧和其他视频内容。而且&#xff0c;Emby还具备强大的媒体管理功能&#xff0c;让您的影视资源井然有序…...

#从零开始# 在深度学习环境中,如何用 pycharm配置使用 pipenv 虚拟环境

为Python项目创建虚拟环境 在深度学习环境和一般python环境中安装pipenv基本一致&#xff0c;只需要确认好pipenv指定的python版本即可,安装pipenv前&#xff0c;可以通过python --version来确认安装版本 快捷键&#xff1a;crtl alt S 查看interpreter&#xff0c;查看所有…...

Cmake编译Opencv3.3.1遇到有些文件无法下载的错误解决:

前言&#xff1a; 对于&#xff0c;opencv有些配置文件错误并未致命&#xff0c;所以&#xff0c;有错误也不影响后续的编译&#xff1a;但是&#xff0c;后引用如果要用&#xff0c;在回过头来还是要解决的。 问题表述&#xff1a; 比如&#xff0c;有些文件下载的错误&am…...

Python基础知识:Python序列以及序列的索引、切片、相乘和相加

索引 索引就是序列中的每个元素所在的位置&#xff0c;可以通过从左往右的正数索引&#xff0c;也可以通过从右往左的负数索引。 从左往右的正数索引&#xff1a;在python序列中&#xff0c;第一个元素的索引值为0&#xff0c;第二个元素的索引值为1&#xff0c;以此类推&…...

回归预测 | 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等技术栈实现的导航网站系统&#xff0c;采用主流的互联网技术架构、全新的UI设计、支持一键源码部署&#xff0c;拥有完整的仪表板、导航管理&#xff0c;用户管理、评论管理…...

SQL查询数据之多表(关联)查询

数据表&#xff1a; 关联查询主要分为&#xff1a;&#xff08;inner join&#xff09;交叉关联、&#xff08;left join&#xff09;左关联、&#xff08;right join&#xff09;右关联 &#xff08;inner join&#xff09;交叉关联&#xff1a; 定义&#xff1a;&#xff0…...

常见的web前端开发框架介绍

Web前端开发框架是为了简化网页设计和开发的流程而创建的工具集。它们提供了预定义的组件、工具和库&#xff0c;帮助开发者快速构建交互式的用户界面。以下是一些常见的Web前端开发框架&#xff0c;以及它们的原理、基础技术和应用场景的介绍&#xff1a; 1. React **…...

CSS 选择器与相关规则详解

CSS&#xff08;Cascading Style Sheets&#xff09;的选择器是网页样式设计中至关重要的工具&#xff0c;它们允许开发者精确地定位并应用样式到HTML文档中的元素。下面将逐一介绍几种主要的选择器类型&#xff0c;以及相关的注释和规则。 1. 类选择器 (Class Selector) 类选…...

基于springboot的宠物店系统的设计与实现

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…...

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&#xff0c;即作为下图中的UI Nodes(Canvas Node)的子节点&#xff0c;和3D组件是隔离开的&#xff0c;不能显示在3D空间中&#xff0c;UI Nodes(Canvas Node)是一个平面内的矩形…...

netstat是一个常用的网络工具,用于显示和分析网络连接、路由表以及网络接口等信息。

netstat 是一个常用的网络工具&#xff0c;用于显示和分析网络连接、路由表以及网络接口等信息。 它可以提供关于网络活动的实时统计数据&#xff0c;包括正在监听的端口、已建立的连接、网络接口的状态等。 使用 netstat 命令可以列出当前系统中的网络连接情况。以下是一些常…...

【Linux】linux权限

linux权限 一&#xff0c;Linux权限的概念二&#xff0c;Linux权限管理1.文件访问者分类2.文件类型和访问权限3.文件权限值的表示方法4.文件访问权限的设置 三&#xff0c;目录的权限四&#xff0c;粘滞位五&#xff0c;权限掩码1.什么是权限掩码2.权限掩码的计算 一&#xff0…...

XUbuntu22.04之如何创建、切换多个工作区(二百零九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...