简单了解一下智能指针(C++)

在了解智能指针之前,需要先了解一下RAII

RAII 是 Resource Acquisition Is Initialization (请求到资源立即初始化)的缩写,它是一种设计思想,在C++里常常通过类进行实现,它在获取资源时把资源委托给一个对象,资源在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源,保障资源正常释放

RAII是智能指针的指导思想

上图中就展示了智能指针是如何运作的,将新申请到的空间给到智能指针之后,不再需要手动释放空间,因为cur 会在生命周期结束时自动析构,析构就销毁了

此时不管程序或者函数 是正常结束还是异常结束,都可以保障new 的资源正常释放

除了要保障析构,智能指针还需要重载运算符,模拟指针的行为

智能指针的问题是拷贝,当两个智能指针指向了同一个空间时,就会导致一个空间被析构两次

c++标准库是怎么解决这个问题的呢

c++标准库有多种智能指针,除了weak_ptr,其它的区别主要是解决拷贝的思路不同

auto_ptr : c++98时设计出来的智能指针,它的特点是拷贝时把被拷贝对象的资源的管理权转移给拷贝对象,这会导致被拷贝对象悬空,建议不要使用,它在c++17已移除

unique_ptr:c++11设计出来的,特点是不支持拷贝,只支持移动

shared_ptr:c++11设计出来的,特点是支持拷贝(底层使用引用计数实现),也支持移动

weak_ptr: c++11设计出来的,它不支持RAII,不能用它直接管理资源,是为了解决shared_ptr的循环引用问题产生的

auto_ptr

可以看到一旦ptr给到ptrcp ,就实现了资源转移,使得ptr悬空

unique_ptr

unique_ptr 不让拷贝,只能移动

shared_ptr

可以拷贝可以移动

原理是 有几个对象指向,引用计数就是几,然后让最后一个管理的对象释放资源

可以看到ptr由于资源被转移,引用计数为0

可以使用reset()手动释放智能指针

智能指针还重载了bool,用来判断智能指针是否为空,如果为空,返回false

虚拟指针特化

需要使用特化版本 接收 申请的连续的内存块

因为shared_ptr和unique_ptr 默认使用的delete析构,而不是使用delete[]析构

早期没有特化时,使用的是仿函数,也就是删除器来对指针进行释放

unique_ptr 传删除器还需要在模板参数里加上类型

循环引用问题

假设有两个节点,节点内部各自有next prev指针 指向之前或者之后的节点,这两个节点互相指向,a节点的next指针指向b节点,b节点的prev指针指向a节点

next指针和prev指针都是shared_ptr智能指针

同时a,b 两个节点都由shared_ptr智能指针管理,分别为n1,n2

此时n1、n2 两个智能指针的引用计数都为2,n1是因为b节点的prev指针,n2是因为a节点的next指针

当我们想要释放 a节点,需要将n1 进行reset(进行计数减减),此时计数为1,还有b节点的 prev指针指向它,此时就可以有两种做法

1、可以将b节点的prev指针进行 reset或者指向其它节点,但是这需要程序员手动进行管理,一旦程序员忘记手动释放或者指向其它节点,就会发生资源泄漏

2、让prev指针进行析构,将b节点进行释放,b节点的成员prev指针自然就进行析构了,但是这又会出现问题,因为b节点无法释放,a节点的next指针指向它,这就形成了循环引用

为了更好的解决a节点释放的问题,就引入了weak_ptr 智能指针,由于weak_ptr 不会增加引用计数,next和prev指针使用weak_ptr进行管理,a节点就不会因为b节点释放不了

可以使用shared_ptr进行构造,内部只是接收了指针,没有接收引用计数

weak_ptr 内部支持expired检查指向的资源有没有过期(没过期就会返回0,过期就会返回1),同时还提供了use_count接口 来获取指向的shared_ptr的引用计数,还可以调用lock 来返回一个shared_ptr对象用来管理自己指向的资源(weak_ptr 是没法访问指向资源的),如果指向资源已经过期,就会返回一个空的shared_ptr对象

相关推荐
温宇飞6 分钟前
内存异常
c++
陌路物是人非17 分钟前
记一个 @Resource BUG
java·开发语言·bug
怎么就重名了20 分钟前
记录Qt的UDP通信丢包问题
开发语言·qt·udp
superman超哥24 分钟前
Rust 闭包的定义与捕获:所有权系统下的函数式编程
开发语言·后端·rust·函数式编程·rust闭包·闭包的定义与捕获
曹牧26 分钟前
Java:Math.abs()‌
java·开发语言·算法
期待のcode32 分钟前
Java的泛型
java·开发语言
沐知全栈开发32 分钟前
PostgreSQL 删除数据库指南
开发语言
!停39 分钟前
c语言动态申请内存
c语言·开发语言·数据结构
AC赳赳老秦39 分钟前
pbootcms模板后台版权如何修改
java·开发语言·spring boot·postgresql·测试用例·pbootcms·建站
代码or搬砖1 小时前
Collections和Arrays
java·开发语言