博客
关于我
【C++11】C++智能指针循环引用问题分析
阅读量:488 次
发布时间:2019-03-06

本文共 2153 字,大约阅读时间需要 7 分钟。

C++11中引入了三种智能指针,分别是shared_ptr、weak_ptr和unique_ptr

智能指针的作用

智能指针可以帮助我们管理动态分配的堆内存,减少内存泄漏的可能性

手动管理堆内存有引起内存泄漏的可能,比如这段代码

try {    int* p = new int;    // Do something    delete p;} catch(...) {    // Catch exception}

如果在执行Do something的时候发生了异常,那么程序就会直接跳到catch语句捕获异常,delete p这句代码不会被执行,发生了内存泄漏

我们把上面的程序改成

try {    shared_ptr
p(new int); // Do something} catch(...) { // Catch exception}

当执行Do something的时候发生了异常,那么try块中的栈对象都会被析构。因此代码中p的析构函数会被调用,引用计数从1变成0,通过new分配的堆内存被释放,这样就避免了内存泄漏的问题

循环引用问题

虽然智能指针会减少内存泄漏的可能性,但是如果使用智能指针的方式不对,一样会造成内存泄漏。比较典型的情况是循环引用问题,比如这段代码

class B; // 前置声明class A {public:    shared_ptr ptr;};class B {public:    shared_ptr ptr;};int main(){    while(true) {        shared_ptr pa(new A());        shared_ptr pb(new B());        pa -> ptr = pb;        pb -> ptr = pa;    }    return 0;}

这个程序中智能指针的引用情况如下图

在这里插入图片描述

上图中,class A和class B的对象各自被两个智能指针管理,也就是pa和pb引用计数都为2,为什么是2?

因为shared_ptr是一组指针指向一个实例,所以有几个shared_ptr指向类A,则类A就有几次引用。,class B对象同理。

在这种情况下,在main函数中一个while循环结束的时候,pa和pb的析构函数被调用,但是class A对象和class B对象仍然被一个智能指针管理,pa和pb引用计数变成1,于是这两个对象的内存无法被释放,造成内存泄漏,如下图所示

在这里插入图片描述

解决方法weak_ptr

std::weak_ptr

避免shared_ptr内存泄漏的利器。👈


smart pointer 三兄弟性格各异。unque_ptr是独来独往,shared_ptr是左拥右抱,而weak_ptr生来就不是为了单打独斗,了解之后你会发现他总是和shared_ptr出双入对。

weak_ptr为什么存在?

特性:

不可使用* 和 ->访问对象

被赋值,不会引起shared_ptr内部计数器值变化(我猜是它严格上来说不具备指针的能力---访问对象)

 

 所以,我们就可以用weak_ptr替代shared_ptr, 看👇例子。

#include 
#include
using namespace std;class B;class A{public: A() { cout << "A's constructor ..." << endl; } ~A() { cout << "A's destructor ..." << endl; } std::weak_ptr
weak_b;};class B{public: B() { cout << "B's constructor ..." << endl; } ~B() { cout << "B's destructor ..." << endl; } std::weak_ptr weak_a;};int main(){ std::shared_ptr aa = make_shared(); //aa->object A aa计数器 1 std::shared_ptr bb = make_shared(); //bb->object B bb计数器 1 aa->weak_b = bb; //计数器还是1哦 bb->weak_a = aa; //计数器还是1哦 return 0;}

 

object A & B都被成功析构(销毁)了。那么循环引用导致shared_ptr发生内存泄漏的问题迎刃而解!

原因是:weak_ptr不会增加shared_ptr的计数器,从而离开mian函数作用域时,shared_ptr aa & bb 计数器都 -1 ,成为0, 具备销毁条件,调用析构函数销毁自己和所指对象

至此,我们终于可以说weak_ptr具备避免内存泄漏的功能了!!!

转载地址:http://hhndz.baihongyu.com/

你可能感兴趣的文章
Nmap渗透测试指南之指纹识别与探测、伺机而动
查看>>
Nmap端口扫描工具Windows安装和命令大全(非常详细)零基础入门到精通,收藏这篇就够了
查看>>
NMAP网络扫描工具的安装与使用
查看>>
NMF(非负矩阵分解)
查看>>
nmon_x86_64_centos7工具如何使用
查看>>
NN&DL4.1 Deep L-layer neural network简介
查看>>
NN&DL4.3 Getting your matrix dimensions right
查看>>
NN&DL4.7 Parameters vs Hyperparameters
查看>>
NN&DL4.8 What does this have to do with the brain?
查看>>
nnU-Net 终极指南
查看>>
No 'Access-Control-Allow-Origin' header is present on the requested resource.
查看>>
No 'Access-Control-Allow-Origin' header is present on the requested resource.
查看>>
NO 157 去掉禅道访问地址中的zentao
查看>>
no available service ‘default‘ found, please make sure registry config corre seata
查看>>
No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
查看>>
no connection could be made because the target machine actively refused it.问题解决
查看>>
No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
查看>>
No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
查看>>
No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
查看>>
No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
查看>>