weak_ptr打破环状引用
转自:http://blog.csdn.net/malong777/article/details/48974559
weak_ptr是一种不控制对象生存周期的智能指针,它指向一个shared_ptr管理的对象...它不会改变shared_ptr的引用计数——《C++ Primer .5th》。很明显,weak_ptr的特点是“弱引用”。有什么用?应用场景是什么地方?
考虑它的胞兄shared_ptr,每次复制之后引用计数加一,不再指向对象(自身销毁或指向其他对象)时时引用计数减一,减至零值调用所管理资源对象的析构函数。考虑这样一个情况,两个对象各自包含指向彼此的shared_ptr成员,形成环状引用,引用计数永远为1,不能销毁,造成内存泄漏。
//x86_64 win7_64 vs2013 ultimate
#include <iostream>
#include <string>
#include <memory>
using namespace std; class A;
class B; class A{
public:
~A(){ cout << "destroying A\n" ; }
shared_ptr<B> pb;
}; class B{
public:
~B(){ cout << "destroying B\n" ; }
shared_ptr<A> pa;
}; void test(){
shared_ptr<A> a(new A());
shared_ptr<B> b(new B()); a->pb = b;
b->pa = a;
} int main(){
cout << "begin test...\n";
test();
cout << "end test\n";
} output:
begin test...
end test
请按任意键继续. . .
在函数test()中便是刚才提到的情形,A、B的对象分别被彼此的shared_ptr所引用,离开test()作用域后,A、B对象再也不能被用户访问,因为智能指针a、b被销毁了,但是各自引用计数为1,两个对象的内存再也不会被释放,可怕的内存泄漏就此产生。
那么weak_ptr对此又有帮助呢?考虑如果将B中的智能指针换成weak_ptr<A>,回过头看test()里发生了什么?首先shared_ptr版本的a、b初始化,引用计数各自为1,然后将b赋值给A中的shared_ptr,B对象引用计数变为2,将a赋值给B中的weak_ptr,此操作不改变shared_ptr<A>的引用计数,依旧为1。退出test作用域,a、b析构,B引用计数变为1,A的引用计数为0。A的析构函数被调用,A中的shared_ptr<B>也被销毁,即B的引用计数再次减1变为0,调用B的析构函数。此时,内存已经被全部回收。
class B{
public:
~B(){ cout << "destroying B\n" << endl; }
weak_ptr<A> pa;
};
output:
begin test...
destroying A
destroying B
end test
请按任意键继续.
实际用用的例子,想象在一个tree结构中,父节点通过一个共享所有权的引用(chared_ptr)引用子节点,同时子节点又必须持有父节点的引用。如果这第二个引用也共享所有权,就会导致一个循环,最终两个节点内存都无法释放。
weak_ptr打破环状引用的更多相关文章
- [转] weak_ptr解决shared_ptr环状引用所引起的内存泄漏
http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引 ...
- weak_ptr解决shared_ptr环状引用所引起的内存泄漏[转]
转载:http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理 ...
- c++interview
出自:https://github.com/huihut/interview Github | Docsify 简体中文 | English 关于 本仓库是面向 C/C++ 技 ...
- [c++] Smart Pointers
内存管理方面的知识 基础实例: #include <iostream> #include <stack> #include <memory> using names ...
- c++101rule
组织策略0,不拘于小结缩进, 行的长度,命名,注释,空格,制表,1-4,高警告级别干净利落地进行编译,使用构建系统,使用版本控制,代码审查风格5,一个实体应该只有一个紧凑的职责. (依赖性管理,继承, ...
- Effective C++ 笔记三 资源管理
条款13:以对象管理资源 许多资源被动态分配于heap内而后被用于单一区块或函数内.它们应该在控制流离开那个区块或函数时被释放.标准程序库提供的auto_ptr正是针对这种形式而设计的特制产品.aut ...
- <转>Python的内存泄漏及gc模块的使用分析
一般来说在 Python 中,为了解决内存泄漏问题,采用了对象引用计数,并基于引用计数实现自动垃圾回收.由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为自己从此过上了好日子,不必再受内 ...
- Effective C++笔记 55条编程法则
1. 视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 2. 尽量以const,enum.inline替代#define 1) 对于单纯常量,最好以const ...
- 《Effective C++》第3章 资源管理(1)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
随机推荐
- oracle官网下载教程
1.百度搜索oracle 也可以直接点击进入 oracle官网 或直接进入 下载页面 2.选择中文,看的更容易些 3.拉到最下面,选择所有下载和试用 4.选择数据库下载 5.点击下载对 ...
- iOS:常用属性、方法
前言:一段时间没接触,很容易就忘记以前的知识.专写一篇,供几个月没接触,拿起却忘记了. 0.宏定义.系统相关 0-1).宏定义.规范 变量: //全局变量通常用小写g来提示 int gNumb=0; ...
- js前台加密,java后端解密
1.前台JS <script type="text/javascript"> $(function() { $(" ...
- ubuntu各系统双网卡绑定
Ubuntu14.04双网卡绑定 2.1 确定网卡名称 首先确定两块网卡的名称,一般为eth0.eth1,如果有自己添加的网卡名称可能不同,在安装系统的时候可以看到,通过ipmaddr命令可以查看所有 ...
- AES加密工具
public class AES { /** * 加密 * * @param content * 需要加密的内容 * @param password * 加密密码 * @return */ publi ...
- 配置vue-devtools调试工具
1. 通过 Git 克隆项目到本地 git clone https://github.com/vuejs/vue-devtools.git 2. Git 进入到 vue-devtools 所在目录,然 ...
- 关于okHttp框架的使用
在之前的项目中,使用传统的HttpClient来返回一个图片信息流的时候总是报错,最后发现是因为传统的传输方式会对流的大小有限制,当超过某个值的时候就会报异常,最后决定使用OkHttp框架来解决这个问 ...
- Axure RP Extension for Chrome安装
Axure RP Extension for Chrome安装 Axure RP Extension for Chrome是一款谷歌插件,主要可以用来查看原型文件.以前安装插件的时候总是找半天资源,很 ...
- [转]不让iTunes备份到c盘
很多人现在的C盘都是空间不大的SSD硬盘,ITUNES备份老是占越来越大的空间,不如动手把它改成其它盘好了.下面7个步骤教你转移备份. 1.需要一个小工具:Juction.exe,如果你已经是WIN7 ...
- 在pythonanywhere上部署Django应用
参考:https://tutorial.djangogirls.org/zh/deploy/ 资料讲的很明了,仅在设置上做几点补充. 1.设置相对路径 import os BASE_DIR = os. ...