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. Codeforces 1093D. Beautiful Graph【二分图染色】+【组合数】

    <题目链接> 题目大意: 给你一个无向图(该无向图无自环,且无重边),现在要你给这个无向图的点加权,所加权值可以是1,2,3.给这些点加权之后,要使得任意边的两个端点权值之和为奇数,问总共 ...

  2. HDU 1301-Jungle Roads【Kruscal】模板题

    题目链接>>> 题目大意: 给出n个城市,接下来n行每一行对应该城市所能连接的城市的个数,城市的编号以及花费,现在求能连通整个城市所需要的最小花费. 解题分析: 最小生成树模板题,下 ...

  3. UVa11988 Broken Keyboard 损坏的键盘【list】

    题目链接:https://vjudge.net/problem/UVA-11988 题目大意: 键盘的home键和end键出现了问题. 在输入一段文本时,home键或end键可能会自动被按下,home ...

  4. the secrets

    prime time productions: my life had collepes arround me? i have worked myselft into exhaustion. my f ...

  5. BZOJ2821 作诗(Poetize) 分块

    题意 算法 经验总结 代码 题意 不带修改,查询数列[1,n]中[l,r]内的出现正偶数次的数的个数, 数列中的数 <= 1e5, n <= 1e5, 强制在线 算法 ​ 查询的内容: 区 ...

  6. Codeforces.GYM100548G.The Problem to Slow Down You(回文树)

    题目链接 \(Description\) 给定两个串\(S,T\),求两个串有多少对相同回文子串. \(|S|,|T|\leq 2\times 10^5\). \(Solution\) 好菜啊QAQ ...

  7. Java并发编程(六)-- 同步块

    上一节已经讲到,使用Synchronzied代码块可以解决共享对象的竞争问题,其实还有其他的方法也可以避免资源竞争问题,我统称他们为Java同步块.Java 同步块(synchronized bloc ...

  8. Idea创建一个Springboot单模块项目

    1.打开IDEA,创建新项目,选择Spring Initializr,选择SDK为你的java版本. 2.点击下一步,输入Artifact 3.点击下一步,选择web 4.finish 5.完成后id ...

  9. Compiling U-Boot

    To configure and build U-Boot for a target board "cd" to, or copy the source tree to somew ...

  10. sql面试题-----行转列

    tem数据表如下图 select Time as 日期, sum ( case end ) as 胜, sum ( case end ) as 负 from tem group by Time 执行结 ...