weak_ptr是为配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手,而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和operator->,它的最大作用在于协助shared_ptr,像旁观者那样观测资源的使用情况。

  但它有一个很大的缺点,那就是不能管理循环引用的对象。  

#include <boost/shared_ptr.hpp>
#include <iostream>
using namespace std; class Parent;
class Child;
typedef boost::shared_ptr<Parent> parent_ptr;
typedef boost::shared_ptr<Child> child_ptr; class Child
{
public:
Child()
{
cout << "Child ..." << endl;
}
~Child()
{
cout << "~Child ..." << endl;
}
parent_ptr parent_;
}; class Parent
{
public:
Parent()
{
cout << "Parent ..." << endl;
}
~Parent()
{
cout << "~Parent ..." << endl;
}
child_ptr child_;
}; int main(void)
{
parent_ptr parent(new Parent);
child_ptr child(new Child);
parent->child_ = child;
child->parent_ = parent; return ;
}
 
        
 
  如上述程序的例子,运行程序可以发现Child 和 Parent 构造函数各被调用一次,但析构函数都没有被调用。由于Parent和Child对象互相引用,它们的引用计数最后都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了内存泄漏。
 
  其中一种解决循环引用问题的办法是 手动打破循环引用,如在return 0; 之前加上一句 parent->child_.reset(); 此时
        
  当栈上智能指针对象child 析构,Child 对象引用计数为0,析构Chlid 对象,它的成员parent_ 被析构,则Parent 对象引用计数减为1,故当栈上智能指针对象parent 析构时,Parent 对象引用计数为0,被析构。
 
但手动释放不仅麻烦而且容易出错,这里主要介绍一下弱引用智能指针 weak_ptr<T> 的用法,下面是简单的定义:
  

amespace boost
{ template<typename T> class weak_ptr
{
public:
template <typename Y>
weak_ptr(const shared_ptr<Y> &r); weak_ptr(const weak_ptr &r); template<class Y>
weak_ptr &operator=( weak_ptr<Y> && r ); template<class Y>
weak_ptr &operator=(shared_ptr<Y> const &r); ~weak_ptr(); bool expired() const;
shared_ptr<T> lock() const;
};
}

两个常用的功能函数:expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用智能指针。

强引用与弱引用

强引用,只要有一个引用存在,对象就不能释放

弱引用,并不增加对象的引用计数(实际上是不增加use_count_, 会增加weak_count_);但它能知道对象是否存在

通过weak_ptr访问对象的成员的时候,要提升为shared_ptr

如果存在,提升为shared_ptr(强引用)成功
如果不存在,提升失败

对于上述的例子,只需要将Parent 类里面的成员定义改为如下,即可解决循环引用问题:

class Parent
{
public:
boost::weak_ptr<parent> child_;
};

      

  因为此例子涉及到循环引用,而且是类成员引用着另一个类,涉及到两种智能指针,跟踪起来难度很大,我也没什么心情像分析shared_ptr 一样画多个图来解释流程,这个例子需要解释的代码远远比shared_ptr 多,这里只是解释怎样使用。

  下面再举个例子说明lock()  和 expired() 函数的用法:

#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include <iostream>
using namespace std; class X
{
public:
X()
{
cout << "X ..." << endl;
}
~X()
{
cout << "~X ..." << endl;
} void Fun()
{
cout << "Fun ..." << endl;
}
};
int main(void)
{
boost::weak_ptr<X> p;
boost::shared_ptr<X> p3;
{
boost::shared_ptr<X> p2(new X);
cout << p2.use_count() << endl;
p = p2;
cout << p2.use_count() << endl; /*boost::shared_ptr<X> */
p3 = p.lock();
cout << p3.use_count() << endl;
if (!p3)
cout << "object is destroyed" << endl;
else
p3->Fun();
}
/*boost::shared_ptr<X> p4 = p.lock();
if (!p4)
cout<<"object is destroyed"<<endl;
else
p4->Fun();*/ if (p.expired())
cout << "object is destroyed" << endl;
else
cout << "object is alived" << endl; return 0;
}

  

  从输出可以看出,当p = p2; 时并未增加use_count_,所以p2.use_count() 还是返回1,而从p 提升为 p3,增加了use_count_, p3.use_count() 返回2;出了大括号,p2 被析构,use_count_ 减为1,程序末尾结束,p3 被析构,use_count_ 减为0,X 就被析构了。

总结:

  weak_ptr是一个“弱”指针,但它能够完成一些特殊的工作,足以证明它的存在价值。

  weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。

  使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count() == 0,但更快,表示观测的资源(也就是shared_ptr管理的资源)已经不复存在了。

  weak_ptr 没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。当expired() == true的时候,lock()函数将返回一个存储空指针的shared_ptr。

weak_ptr<T>智能指针的更多相关文章

  1. c++11 智能指针 unique_ptr、shared_ptr与weak_ptr

    c++11 智能指针 unique_ptr.shared_ptr与weak_ptr C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer), ...

  2. c++11之智能指针

    在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存.这种内存管理的方式只需要程序员将new操作返 ...

  3. auto_ptr,shared_ptr 智能指针的使用

    Q: 那个auto_ptr是什么东东啊?为什么没有auto_array?A: 哦,auto_ptr是一个很简单的资源封装类,是在<memory>头文件中定义的.它使用“资源分配即初始化”技 ...

  4. c++ 智能指针、函数指针和指针函数

    智能指针: 1.内存泄漏memory leak :是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出. 2.内存溢出 out of me ...

  5. 智能指针 - 现代C++新特性总结

    C++98中的智能指针通过一个模板类auto_ptr来实现,new操作符返回的指针可以交由它来管理,程序员不用再显式的调用delete,这在一定程度上避免了堆内存忘记释放的问题:不过auto_ptr有 ...

  6. [6] 智能指针boost::weak_ptr

    [1]boost::weak_ptr简介 boost::weak_ptr属于boost库,定义在namespace boost中,包含头文件 #include<boost/weak_ptr.hp ...

  7. C++智能指针--weak_ptr

    weak_ptr是对对象的一种弱引用,它不会添加对象的引用计数.weak_ptr和shared_ptr之间能够相互转换.shared_ptr能够直接赋值给week_ptr,week_ptr可通过调用l ...

  8. stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

    stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...

  9. c++——智能指针学习(shared_ptr和weak_ptr)

    先看一个例子:Stark和Targaryen家族你中有我,我中有你.我们设计以下类企图避免内存泄漏,使得析构函数都能调用到: #include<iostream> #include< ...

随机推荐

  1. Vue 中 computed、watch对比

    computed:就像调用VUE的DATA一样 watch的对比 :监听事件

  2. JavaEE 之 文件上传

    1.文件上传 a.配置mySpring-servlet.xml <bean id="multipartResolver" class="org.springfram ...

  3. poj1041 【无向图欧拉回路】 按最小升序输出

    题目链接:http://poj.org/problem?id=1041 题目大意: 题目大意:一个城镇有n个二叉路口,这些路口由m条街道连接,某人想要从某个路口出发,经过所有的街道且每条街道只走一次, ...

  4. [ 高危 ]mt某站SQL注入

    RANK 24 金币    24 等价RMB  240 与上一漏洞同源所以只有24 数据包: GET /check?clientId=64915 HTTP/1.1 Host: xxx.meituan. ...

  5. 如何删除pagefile.sys

    经常使用电脑的用户就会发现系统自带了虚拟内存文件pagefile.sys,若是电脑出现内存不足情况,其就会调用虚拟内存来执行程序,以防止系统内存崩溃.不过,虚拟内存没有真实的内存读取速度快,而且会占用 ...

  6. Unity容器在asp.net mvc中的IOC应用及AOP应用

    <asp.net-mvc框架揭秘>一书中,有个示例,是使用unity容器来注入自定义的控制器工厂.代码示例可以自己去下载源码,在这里我就不说了.IOC容器的本质是解耦的实例化接口类,而如何 ...

  7. 【C#】 break continue return 的区别

    static void Main(string[] args) { Console.WriteLine("使用break退出循环"); ; i < ; i++) { ) { ...

  8. 想造轮子的时候,ctrl+f一下

    Chardet,字符编码探测器,可以自动检测文本.网页.xml的编码. colorama,主要用来给文本添加各种颜色,并且非常简单易用. Prettytable,主要用于在终端或浏览器端构建格式化的输 ...

  9. Xamarin Essentials教程构建共享请求

    Xamarin Essentials教程构建共享请求 共享请求类ShareTextRequest可以用于构建复杂形式的数据,用于向其他应用传输.例如,它可以指定共享内容的主题Subject,用于给邮件 ...

  10. 使用C#的is、as操作符来转型

    is检查对象是否兼容于指定类型,返回Boolean值true或false.使用is永远不会抛出异常. 例:Object o=new Object(); bool b1=(o is Object);// ...