【C++】智能指针——auto_ptr,unique_ptr,shared_ptr

server/2024/10/22 14:05:38/

目录

auto_ptr

unique_ptr

shared_ptr

并发问题

循环引用问题


个人主页:传送门——>东洛的克莱斯韦克

智能指针的原理:传送门——>智能指针的原理

auto_ptr

使用方法参考官方文档

传送门——>auto_ptr文档

auto_ptr并不是一个优秀的智能指针,它的设计理念是——管理权转移。如下代码示意

auto_ptr(auto_ptr<T>& sp):_ptr(sp._ptr){// 管理权转移sp._ptr = nullptr;}

旧的智能指针的会转移给新的智能指针,而旧的智能指针的会被置空。所以就有一个很严重的问题——如果对置空的智能指针做了加加减减等操作呢?如下代码示意

int main()
{std::auto_ptr<int> sp1(new int);std::auto_ptr<int> sp2(sp1); // 管理权转移//sp1悬空*sp2 = 10;cout << *sp2 << endl;cout << *sp1 << endl;return 0;
}

auto_ptr是一个失败设计,很多公司明确要求不能使用auto_ptr

unique_ptr

使用方法参考官方文档

传送门——>unique_ptr文档

unique_ptr智能指针的设计理念很简单——防拷贝。也就是说一份资源只能由一个unique_ptr管理,如下代码示意

unique_ptr(const unique_ptr<T>& sp) = delete;unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;

shared_ptr

使用方法参考官方文档

传送门——>shared_ptr文档

不同于unique_ptr,shared_ptr的允许多个智能指针管理同一份资源。shared_ptr采用引用计数的机制来判断一个资源是否允许被销毁

shared_ptr的引用计数是额外申请了空间(并没有在类的内部),它的设计是由一个指针指向一块空间,该空间存放计数。这种设计难免会有内存碎片的问题

代码示意

shared_ptr(T* ptr = nullptr):_ptr(ptr), _pRefCount(new int(1)) //额外开辟空间, _pmtx(new mutex){}

并发问题

引用计数本身是有并发问题的,关于线程,并发,锁相关知识可参考小编另一篇文章。

传送门——>线程,并发,锁

1.智能指针对象中引用计数是多个智能指针对象共享的,两个线程中智能指针的引用计数同时 ++或--,这个操作不是原子的,引用计数原来是1,++了两次,可能还是2.这样引用计数就错 乱了。会导致资源未释放或者程序崩溃的问题。所以只能指针中引用计数++、--是需要加锁 的,也就是说引用计数的操作是线程安全的。

2. 智能指针管理的对象存放在堆上,两个线程中同时去访问,会导致线程安全问题。

所以引用计数的加加减减操作是加锁的。如下代码示意

void Release(){_pmtx->lock();bool flag = false;if (--(*_pRefCount) == 0 && _ptr){cout << "delete:" << _ptr << endl;delete _ptr;delete _pRefCount;flag = true;}_pmtx->unlock();if (flag == true){delete _pmtx;}}void AddRef(){_pmtx->lock();++(*_pRefCount);_pmtx->unlock();}

循环引用问题

该问题是有类似于链表节点的结构引起的,当外部的智能指针都释放了,就拿不内部的智能指针,那么节点就不会释放

解决方案:在引用计数的场景下,把节点中的_prev和_next改成weak_ptr就可以了,weak_ptr不会增加引用计数,代码示意

struct ListNode
{int _data;weak_ptr<ListNode> _prev;weak_ptr<ListNode> _next;
};


http://www.ppmy.cn/server/110292.html

相关文章

【Google Play版】bilibili 3.19.2最新国际版(如何鉴别是否官方?)

相信玩 B 站的小伙伴也不少&#xff0c;国内版确实太臃肿了&#xff0c;已经“变质”了。 这是主界面&#xff0c;我没有做任何设置&#xff0c;刚装好就是这样&#xff1a; 摘自 Play 最新的评论&#xff1a; “3.19非常好&#xff0c;解决了我之前两个痛点。一是首页的自动…

使用libbpf-bootstrap框架构建eBPF程序

使用libbpf-bootstrap框架构建eBPF程序 在公众号写了一篇文章&#xff0c;可以参考如上链接。

算法训练营|图论第7天 prim算法 kruskal算法

题目&#xff1a;prim算法 题目链接&#xff1a; 53. 寻宝&#xff08;第七期模拟笔试&#xff09; (kamacoder.com) 代码&#xff1a; #include<bits/stdc.h> #include<unordered_map> #include<unordered_set> using namespace std; int main() {int v…

Redis的内存淘汰策略- allkeys-lru

allkeys-lru 策略简介 在 allkeys-lru 策略下&#xff0c;当 Redis 的内存使用达到设置的上限&#xff08;maxmemory&#xff09;时&#xff0c;它会根据 LRU 算法选择和删除那些最近最少使用的键。LRU 算法会记录每个键的最近访问时间&#xff0c;当内存不足时&#xff0c;Re…

MySQL——事务与存储过程(二)存储过程的创建(1)创建存储过程

在开发过程中&#xff0c;经常会遇到重复使用某一功能的情况&#xff0c;为此&#xff0c;MySQL 引人了存储过程。存储过程就是一条或多条 SQL语句的集合&#xff0c;当对数据库进行一系列复杂操作时&#xff0c;存储过程可以将这些复杂操作封装成一个代码块&#xff0c;以便重…

JavaWeb笔记整理11——Nginx反向代理Tomcat

Nginx反向代理Tomcat服务器的实现原理&#xff1a; Nginx 就像一个中间人&#xff0c;它站在你的客户端&#xff08;比如浏览器&#xff09;和后端服务器&#xff08;比如Tomcat&#xff09;之间。它的主要任务是接收来自客户端的请求&#xff0c;然后将这些请求转发给实际处理…

【GPT】Coze使用开放平台接口-【5】API 调用

我们在机器人里面引用工作流&#xff0c;当然也可以通过 API 直接调用工作流&#xff0c;coze 也提供了这一套的 API 接口。coze 的 API 接口肯定也不只是接入工作流&#xff0c;Bots&#xff0c;文件&#xff0c;知识库等&#xff0c;都有相关接口。这个文档我们也只专注在工作…

怎样通过bs4找出程序中 标签<div class=“List2“>的内容?

怎样通过bs4找出程序中 标签<div class"List2">的内容&#xff1f; 可以使用BeautifulSoup库&#xff08;bs4&#xff09;的find方法来找到程序中带有特定class属性的<div>标签&#xff0c;并通过.text属性获取其内容。 以下是一个示例代码&#xff1a;…