C++进阶--智能指针

智能指针的概念

智能指针是C++中的一个重要概念,用于管理动态分配的对象内存它是一个类模板,通过封装原始指针,并在对象生命周期结束时自动释放内存,从而避免了内存泄漏和资源管理的繁琐工作

C++标准库提供了多种常见的智能指针,目前常用的有:unique_ptr , shared_ptr , weak_ptr。(头文件: < memory >

为什么需要智能指针?

看一个例子:

int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0错误");return a / b;
}
void Func()
{// 1、如果p1这里new 抛异常会如何?// 2、如果p2这里new 抛异常会如何?// 3、如果div调用这里又会抛异常会如何?int* p1 = new int;int* p2 = new int;cout << div() << endl;delete p1;delete p2;
}
int main()
{try{Func();}catch (exception& e){cout << e.what() << endl;}return 0;
}

在这里插入图片描述

RAll

RAII(Resource Acquisition Is Initialization)的核心思想是资源的获取和释放应该与对象的生命周期绑定在一起。当一个对象被创建时,它应该获取所需要的资源;当对象被销毁时,它应该释放已经获取的资源。这样可以确保资源在不再需要时被正确释放,从而避免资源泄漏。

利用RAll原理做出智能指针

代码:

template<class T>
class SmartPtr
{
public://RALLSmartPtr(T* ptr):_ptr(ptr){}~SmartPtr(){cout << "delete: " << _ptr<< endl;delete _ptr;}//解引用T& operator*(){return *_ptr;}//指针形式T* operator->(){return _ptr;}
private:T* _ptr;
};

利用RAll原理制作智能指针:
在这里插入图片描述
在这里插入图片描述

测试:在这里插入图片描述
在这里插入图片描述

auto_ptr

在这里插入图片描述

简单使用

在这里插入图片描述
在这里插入图片描述
由于这种智能指针不能对实际应用起到作用,所以现在大多数程序员都没有用到它。

要模拟实现一个auto_ptr时,只需要在上面代码的赋值拷贝中加上:
在这里插入图片描述

unique_ptr

unique_ptr与常规指针的一个主要区别就是:它拥有对指向对象的独占拥有权。这意味着同一时间只能有一个unique_ptr指向某个对象,不能进行复制操作,只能进行移动操作。当unique_ptr被销毁或重置时,他所指向的对象也会自动删除。

模拟实现

template<class T>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}unique_ptr(unique_ptr<T>& p)= delete;unique_ptr operator=(const unique_ptr<T>& p) = delete;~unique_ptr(){cout << "delete:" << _ptr << endl;delete _ptr;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

实现时只需要对默认拷贝构造和默认赋值构造给它删除了,那么就实现了不能对它进行复制了。

测试:
在这里插入图片描述

shared_ptr

在这里插入图片描述

为什么不能用static成员来进行计数?

在这里插入图片描述

模拟实现

template<class T>class shared_ptr{public://常规使用的构造函数shared_ptr(T* ptr = nullptr): _ptr(ptr),_count(new int(1)){}//sp2(sp1)shared_ptr(const shared_ptr<T>& sp){_ptr = sp._ptr;_count = sp._count;//拷贝后将count+1++(*_count);}//sp3=sp1shared_ptr<T>& operator=(const shared_ptr<T>& sp){if (_ptr != sp._ptr){//使用赋值时,要考虑之前的智能指针指向的空间release();_ptr = sp._ptr;_count = sp._count;//拷贝后将count+1++(*_count);}return *this;}//释放资源void release(){if (--(*_count) == 0){cout << "delete:" << _ptr << endl;delete _ptr;delete _count;}}~shared_ptr(){//当count为0时触发release();}int use_count(){return *_count;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get() const{return _ptr;}private:T* _ptr;int* _count;};

解释:
在这里插入图片描述

测试:
在这里插入图片描述

赋值时必须要对之前智能指针指向的空间进行检查:
在这里插入图片描述

验证解引用:
在这里插入图片描述

定制删除器

在这里插入图片描述
在类中添加一个成员:
在这里插入图片描述
在这里插入图片描述
添加一个构造函数的重载:
在这里插入图片描述
在这里插入图片描述
释放时的修改:
在这里插入图片描述

template <class T>
struct ArrayDelete
{void operator()(T* ptr){delete[] ptr;}
};
//定制删除器
int main()
{fnc::shared_ptr<ListNode> n(new ListNode(10));fnc::shared_ptr<ListNode> n1(new ListNode[10],ArrayDelete<ListNode>());fnc::shared_ptr<FILE> n2(fopen("FileName.cpp", "r"), [](FILE* file) {fclose(file); });
}

在这里插入图片描述

智能指针的缺陷

struct ListNode
{int _val;fnc::shared_ptr<ListNode> _next;fnc::shared_ptr<ListNode> _prev;ListNode(int val=0):_val(val){}
};int main()
{fnc::shared_ptr<ListNode> n1(new ListNode(10));fnc::shared_ptr<ListNode> n2(new ListNode(20));cout << n1.use_count() << endl;cout << n2.use_count() << endl;n1->_next = n2;n2->_prev = n1;cout << n1.use_count() << endl;cout << n2.use_count() << endl;//delete n1;//delete n2;return 0;
}

结果:
在这里插入图片描述
在这里插入图片描述

weak_ptr

weak_ptr就是用于解决循环引用的问题。它与shared_ptr配合使用,可以指向一个由shared_ptr管理的对象,但不会增加该对象的引用计数。

weak_ptr不拥有所指对象的拥有权,当指向对象被释放时,weak_ptr会自动失效,不再指向有效的对象

	template<class T>class weak_ptr{public:// RAllweak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& sp){_ptr = sp.get();}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

将LIstNode的next指针和prev指针类型改为weak_ptr的:
在这里插入图片描述
结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/652473.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用PyCharm开发工具创建工程

一. 简介 前面文章实现了开发 python程序使用的 开发工具PyCharm&#xff0c;本文来学习使用 PyCharm开发工具创建一个 python工程。 二. 使用PyCharm开发工具创建工程 1. 首先&#xff0c;打开 PyCharm开发工具&#xff0c;打开 "New project" 选项&#xff1a; …

目标检测的mAP、PR指标含义

基本概念 什么是一个任务的度量标准。对于目标检测任务来说&#xff0c;它的首要目标是确定目标的位置并判别出目标类别。这里已医学图像为例&#xff0c;我们需要计算出血液红细胞&#xff08;RBC&#xff09;、白细胞&#xff08;WBC&#xff09;和血小板的数量。为了实现这一…

安卓悬浮窗权限检查

目录 悬浮窗权限代码检测悬浮窗功能 悬浮窗权限 请求了这个权限后&#xff0c;app的权限管理中会有「显示悬浮窗」的权限选项。后面会引导用户去开启这个权限。 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />代码检测悬浮窗功能…

Week1

1. 题目背景 给定一个N*M方格的迷宫&#xff0c;迷宫里有T处障碍&#xff0c;障碍处不可通过。给定起点坐标和终点坐标&#xff0c;问: 每个方格最多经过1次&#xff0c;有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式&#xff0c;每次只能移动一个方格。…

CH4INRULZ-v1靶机练习实践报告

CH4INRULZ-v1靶机练习实践报告 1 安装靶机 靶机是.ova文件&#xff0c;需要用VirtualBox打开&#xff0c;但我习惯于使用VMWare,因此修改靶机文件&#xff0c;使其适用于VMWare打开。 解压ova文件&#xff0c;得到.ovf文件和.vmdk文件。直接用VMWare打开.ovf文件即可。 2 夺…

Xilinx 7系列中clock IP核通过AXI4-Lite接口实现动态重新配置

当选择了动态重配置&#xff08;Dynamic Reconfiguration&#xff09;选项时&#xff0c;AXI4-Lite接口将默认被选中用于重新配置时钟组件。动态重新配置可以通过AXI4-Lite接口实现了Clocking Wizard IP核的时钟组件MMCM/PLL的动态重新配置。 如果需要直接访问MMCM/PLL的DRP寄…

while循环与for进阶

在循环结构中&#xff0c;一共有4种语句&#xff1a;while、do-while、for、goto。其中&#xff0c;for循环是最复杂的。在本篇文章中&#xff0c;我们将学习while循环与for循环的进阶。 while循环 while循环的结构比较简单&#xff0c;如下&#xff1a; while(循环判断){循…

流量网关与服务网关的区别:(面试题,掌握)

流量网关&#xff1a;&#xff08;如Nignx&#xff0c;OpenResty&#xff0c;Kong&#xff09;是指提供全局性的、与后端业务应用无关的策略&#xff0c;例如 HTTPS证书认证、Web防火墙、全局流量监控&#xff0c;黑白名单等。 服务网关&#xff1a;&#xff08;如Spring Clou…

vue echarts折线图 折线堆积图和折线面积图

vue echarts折线图 折线堆积图和折线面积图 1、折线堆积图和折线面积图的结合&#xff1b; 上代码 <template><section><divid"performaceLineChart"ref"performaceLineChartRef"style"width: 100%; height: 500px"></d…

云计算和边缘计算究竟有什么不同

在数据时代&#xff0c;无论是人的活动还是机器的运作都会产生各种各样海量的数据。在对数据梳理和筛选过程中&#xff0c;计算机的运算处理必不可少。为了减少本地计算机算力成本等限制&#xff0c;越来越多的企业选择了云计算和边缘计算。今天&#xff0c;德迅云安全就带您来…

qt实现方框调整

效果 在四周调整 代码 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QWidget>class MainWindow : public QWidget {Q_OBJECT public:explicit MainWindow(QWidget *parent 0);~MainWindow();void paintEvent(QPaintEvent *event);void updateRect();void re…

MySQL B+索引的工作原理及应用

引言 在数据库系统中&#xff0c;索引是优化查询、提高性能的关键技术之一。特别是在MySQL数据库中&#xff0c;B树索引作为最常用的索引类型&#xff0c;对数据库性能有着至关重要的影响。本文旨简单解析MySQL中B树索引的工作原理&#xff0c;帮助学生朋友们更好地理解和利用…