智能指针循环引用——你真的懂了吗?
相信不少同学都在面试中都被问到过c++智能指针的问题,接踵而至的必定是循环引用了,而我每次的答案都是一招鲜:因为它们都在互相等待对方先释放,所以造成内存泄漏。面试官很满意,我也很满意。
但是为啥要等到对方先释放?在我内心也曾有个问号。。
智能指针起源
所谓人类进步的阶梯就是懒,曾几何时,就有人想,我把new 运算符返回的指针p交给一个对象“托管”,而不用操心在哪里去释放这个指针p,由这个托管者自动的在合适的时机进行指针p的释放,这样也不怕自己忘记释放指针p了。而且,我这边操作托管者,要跟操作原来的指针一毛一样,这样才方便。即假设托管指针p的对象叫做shared_ptr,那么
*shared_ptr 所指,便是 *p 所向!
第一章 auto_ptr
最早的智能指针类,实现了*运算符。你用它实例化出来一个类对象,用起来就好像指针一样。对象的特性自然是在作用域结束时,自动调用析构函数实现自我销毁。如此一来,攻城狮们便可不再操心何时释放指针,而可以随心所欲的摸鱼啦。
但其有个致命缺陷:因为其缺省的复制和赋值构造函数,带来的同一个对象被多个智能指针托管,释放的时候便混乱异常,一不小心就重复释放了,使得用户使用起来战战兢兢,老早就被淘汰了。
第二章 unique_ptr
为了规避auto_ptr可以随意复制和赋值构造的缺陷,就推出了unique_ptr, 其实就是给auto_ptr简单换了个名字,并禁用掉其默认的复制和赋值构造函数,好嘛,大家都别用了<(`^′)>,不写代码,就不会有bug!
第三章 shared_ptr
只有一个unique_ptr,对于省吃俭用的高级攻城狮们来说自然是不够的,于是就有人站了出来喊了一声:我们要搞共享经济——砰!基于引用计数的shared_ptr横空出世了,每多一个人持有这个对象,引用计数就加一;每少一个人持有这个对象,引用计数就减一。引用计数为零时,才做真正的销毁操作。
很快,梦魇悄然而至,“我的shared_ptr怎么没有释放?”——一位焦头烂额的格子少年路过。。
起初,没有人在意这场灾难,这不过是一个指针的丢失、一个bug,一个服务器的宕机,直到这场灾难和每个人息息相关......
"你看这个人写的代码,它好像一坨狗屎"
#include <iostream>class B;
class A {
public:A() {std::cout << "A" << std::endl;}~A() {std::cout << "~A" << std::endl;}
public:std::shared_ptr<B> ptr;
};class B {
public:B() {std::cout << "B" << std::endl;}~B() {std::cout << "~B" << std::endl;}
public:std::shared_ptr<A> ptr;
};void fun() {std::shared_ptr<A> pa(new A());std::shared_ptr<B> pb(new B());pa->ptr = pb;pb->ptr = pa;
}int main()
{fun();return 0;
}
运行结果我不敢看: (*/ω\*)
纳尼?A和B的析构函数都没有被调用,妥妥的内存泄漏了!
事后,据某位亲身经历这次事件的大牛回忆说:“喔,当时的内存布局是这个样子的!”
“对象A同时被pa和对象B中的ptr两个智能指针托管,所以引用计数为2;对象B同时被pb和对象
A中的ptr两个智能指针托管,所以引用计数也为2。那么当fun函数执行完,栈对象pb、pa依次开始执行这样的析构函数:”
// 大牛随手写的析构函数伪代码
// Copyright 2022 DaNiu. All rights reserved.if (--ref_cnt == 0) delete obj;
“紧接着内存布局就变成了这样:”
“pa和pb已经销毁了,然而对象A和B,已经迷失在这浩瀚内存中,亘古难灭。。。吾称之为循环引用!”
路人震惊:“嘶!随着这样的迷失越来越多,这片天地再也无人可搞对象!!!”
゜゜(´O`) ゜゜。:“不要啊!我还没有搞过对象呢。”
......
庆幸的是,不就之后,有人就在shared_ptr出世的那方世界的一个不起眼的角落里,发现了一个小家伙,伴shared_ptr而生。
终章 weak_ptr
为了解决shared_ptr在在循环引用中存在的资源泄漏问题,weak_ptr在这种场景下应用而生,weak_ptr指向的智能指针对象,其引用计数不会加一,也就不会存在无法释放的问题了。
解决的方法就是,把A和B其中的一个ptr改成weak_ptr。
智能指针循环引用——你真的懂了吗?相关推荐
- 智能指针循环引用问题
智能指针循环引用 循环引用简单来说就是:两个对象互相使用一个shared_ptr成员变量指向对方,这会造成循环引用.导致引用计数失效,内存无法释放. #include <iostream> ...
- [zz] C++智能指针循环引用解决
转载自:http://blog.csdn.net/segen_jaa/article/details/8080167 参考文章:http://www.cnblogs.com/TianFang/arch ...
- VTK修炼之道80:VTK开发基础_智能指针与引用计数
1.引用计数 VTK经过多年的开发与维护,已经形成了一套稳定的框架和开发规则.因此,了解这些规则和框架是定制VTK类的基础,这其中用到了大量面向对象的设计模式,例如对象工程模式.观察者/命令模式:还有 ...
- c++智能指针与引用计数
一. 引用计数 先写一个简单的学生类 #include<iostream> #include <string.h> using namespace std;class stud ...
- C++(9)--裸指针、智能指针、引用
指针 1.裸指针的基本概念 1.1 裸指针的声明*/初始化& 1.2 操作裸指针--间接运算符* 1.3 裸指针使用 demo--指向一个简单变量 1.4 空指针--nullptr 1.5 特 ...
- 智能指针shared_ptr引用计数工作原理
引用计数原理 shared_ptr的实现是这样的: shared_ptr模板类有一个__shared_count类型的成员_M_refcount来处理引用计数的问题.__shared_count也是 ...
- 指针与数组——你真的懂么?
文章目录 本文目的 地址类型 与 指针变量 什么是数组 数组的数组 多维数组的区别 a[0] []运算符本质 指向数组的指针 int (*p)[9]; 字符串常量 c语言声明 复杂指针解析:右左法则 ...
- C++总结8——shared_ptr和weak_ptr智能指针
http://blog.csdn.net/wendy_keeping/article/details/75268687 智能指针的提出:智能指针是存储指向动态分配对象指针的类,用于生存期控制.能够确保 ...
- C++ — 智能指针的简单实现以及循环引用问题
http://blog.csdn.net/dawn_sf/article/details/70168930 智能指针 _________________________________________ ...
最新文章
- docker 容器中的 uid 和 gid
- 《How Tomcat Works》读书笔记(二)
- Oracle 11g Release 2 (11.2) for Microsoft Windows (32-Bit)安装与卸除
- Knative 实战:三步走!基于 Knative Serverless 技术实现一个短网址服务
- Training的第十六天
- 密码学 区块链中的应用专栏 【简介】
- ajax兼容低版本浏览器
- 不同文件格式打开的方法
- 重发布直连路由到 OSPF
- Linux好用命令之base64命令
- 国外创业者分享之Android 与 iOS:猜猜哪个能让开发者赚得更多
- 基础操作案例:ArcGIS PRO基础教程(二)
- 易经的奥秘》笔记--台湾师范大学曾仕强
- 当年明月、袁腾飞、阎崇年三人的专业水平的比较以及由此想到的一些学习方法、品书原则
- 百度地图实现公司位置的定位,可拖动修改公司位置。
- 点阵屏HCMS-3977驱动
- php 屏蔽浸膏,【佳学基因】副甲状腺浸膏基因检测
- matlab 调用摄像头拍照
- 终年57岁!中国科学院院士因病逝世
- 人工神经网络教程第四版,人工神经网络教程视频