转自: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打破环状引用的更多相关文章

  1. [转] weak_ptr解决shared_ptr环状引用所引起的内存泄漏

    http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引 ...

  2. weak_ptr解决shared_ptr环状引用所引起的内存泄漏[转]

    转载:http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理 ...

  3. c++interview

    出自:https://github.com/huihut/interview Github    |    Docsify 简体中文    |    English 关于 本仓库是面向 C/C++ 技 ...

  4. [c++] Smart Pointers

    内存管理方面的知识 基础实例: #include <iostream> #include <stack> #include <memory> using names ...

  5. c++101rule

    组织策略0,不拘于小结缩进, 行的长度,命名,注释,空格,制表,1-4,高警告级别干净利落地进行编译,使用构建系统,使用版本控制,代码审查风格5,一个实体应该只有一个紧凑的职责. (依赖性管理,继承, ...

  6. Effective C++ 笔记三 资源管理

    条款13:以对象管理资源 许多资源被动态分配于heap内而后被用于单一区块或函数内.它们应该在控制流离开那个区块或函数时被释放.标准程序库提供的auto_ptr正是针对这种形式而设计的特制产品.aut ...

  7. <转>Python的内存泄漏及gc模块的使用分析

    一般来说在 Python 中,为了解决内存泄漏问题,采用了对象引用计数,并基于引用计数实现自动垃圾回收.由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为自己从此过上了好日子,不必再受内 ...

  8. Effective C++笔记 55条编程法则

    1.  视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 2.  尽量以const,enum.inline替代#define 1) 对于单纯常量,最好以const ...

  9. 《Effective C++》第3章 资源管理(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

随机推荐

  1. oracle官网下载教程

    1.百度搜索oracle   也可以直接点击进入   oracle官网   或直接进入   下载页面 2.选择中文,看的更容易些 3.拉到最下面,选择所有下载和试用 4.选择数据库下载 5.点击下载对 ...

  2. iOS:常用属性、方法

    前言:一段时间没接触,很容易就忘记以前的知识.专写一篇,供几个月没接触,拿起却忘记了. 0.宏定义.系统相关 0-1).宏定义.规范 变量: //全局变量通常用小写g来提示 int gNumb=0; ...

  3. js前台加密,java后端解密

    1.前台JS <script type="text/javascript">        $(function() {                $(" ...

  4. ubuntu各系统双网卡绑定

    Ubuntu14.04双网卡绑定 2.1 确定网卡名称 首先确定两块网卡的名称,一般为eth0.eth1,如果有自己添加的网卡名称可能不同,在安装系统的时候可以看到,通过ipmaddr命令可以查看所有 ...

  5. AES加密工具

    public class AES { /** * 加密 * * @param content * 需要加密的内容 * @param password * 加密密码 * @return */ publi ...

  6. 配置vue-devtools调试工具

    1. 通过 Git 克隆项目到本地 git clone https://github.com/vuejs/vue-devtools.git 2. Git 进入到 vue-devtools 所在目录,然 ...

  7. 关于okHttp框架的使用

    在之前的项目中,使用传统的HttpClient来返回一个图片信息流的时候总是报错,最后发现是因为传统的传输方式会对流的大小有限制,当超过某个值的时候就会报异常,最后决定使用OkHttp框架来解决这个问 ...

  8. Axure RP Extension for Chrome安装

    Axure RP Extension for Chrome安装 Axure RP Extension for Chrome是一款谷歌插件,主要可以用来查看原型文件.以前安装插件的时候总是找半天资源,很 ...

  9. [转]不让iTunes备份到c盘

    很多人现在的C盘都是空间不大的SSD硬盘,ITUNES备份老是占越来越大的空间,不如动手把它改成其它盘好了.下面7个步骤教你转移备份. 1.需要一个小工具:Juction.exe,如果你已经是WIN7 ...

  10. 在pythonanywhere上部署Django应用

    参考:https://tutorial.djangogirls.org/zh/deploy/ 资料讲的很明了,仅在设置上做几点补充. 1.设置相对路径 import os BASE_DIR = os. ...