[内存管理]智能指针的好帮手weak_ptr

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

 

类摘要:

template<class T> class weak_ptr{
     public:
	 weak_ptr();
	 template<class Y> weak_ptr(shared_ptr<Y> const & r);
	 weak_ptr(weak_ptr const & r);
	 
	 ~weak_ptr();
	 weak_ptr & operator=(weak_ptr const &r);
	 
	 long use_count() const;
	 bool expired() const;
	 shared_ptr<T> lock() const;
	 
	 void reset();
	 void swap(weak_ptr<T> &b);	
};


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。

 

使用示例:

int main(){
   shared_ptr<int> sp(new int(10));
   assert(sp.use_count() == 1);
   //create a weak_ptr from shared_ptr
   weak_ptr<int> wp(sp);
   //not increase the use count
   assert(sp.use_count() == 1);
   //judge wp is invalid
   //expired() is equivalent with use_count() == 0
   if(!wp.expired()){
      shared_ptr<int> sp2 = wp.lock();//get a shared_ptr
      *sp2 = 100;
      assert(wp.use_count() == 2);
      cout << *sp2 << endl;
   }//out of scope,sp2 destruct automatically,use_count()--;
   assert(wp.use_count() == 1);
   sp.reset();//shared_ptr is invalid
   assert(wp.expired());
   assert(!wp.lock());
}


获得this的shared_ptr

weak_ptr的一个重要用途是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己:对象使用weak_ptr观测this指,这并不影响引用计数,在需要的时候就调用lock()函数,返回一个符合要求的shared_ptr使外界使用。

这个解决方案被实现为一个惯用法,在头文件<booost/enable_shared_from_this.hpp>定义了一个助手类enable_shared_from_this<T>,其声明如下:

template<class T>
class enable_shared_from_this
{
public:
   shared_ptr<T> shared_from_this();
}


使用的时候只需要让想被shared_ptr管理的类从它继承即可,成员函数shared_from_this()会返回this的shared_ptr

使用示例:

#include <iostream>
#include <boost/smart_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
using namespace std;
class self_shared:
public enable_shared_from_this<self_shared>{
	public:
    self_shared(int n):x(n){}
    int x;
    void print(){
    cout << "self_shared:" << x << endl;
    }
};
int main(){
    shared_ptr<self_shared> sp = 
	                       make_shared<self_shared>(315);
	sp->print();
	shared_ptr<self_shared> p = sp->shared_from_this();
	p->x = 100;
	p->print();	

}


运行结果:

self_shared:315
self_shared:100

 

需要注意的是千万不能从一个普通对象(非shared_ptr)使用shared_from_this ()获取shared_ptr,如

self_shared ss;

shaerd_ptr<self_shared> p = ss.shared_from_this();//error

 

这样虽然语法上能通过,编译也无问题,但在运行时会导致shared_ptr析构时企图删除一个栈上分配的对象,发生未定义行为。

 

关于intrusive_ptr

intrusive_ptr是一个侵入式的引用计数型指针,它可以用于以下情形:

对内存占用的要求非常严格,要求必须与原始指针一样;

现存代码已经有了引用计数机制管理的对象。

boost库不推荐intrusive_ptr,因为shared_ptr已经非常强大且灵活,工作得足够好,可以满足绝大部分(99.99%)的需要。

如果有兴趣,可以自行翻阅boost文档。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
智能指针是C++中用于管理动态分配的内存的一种机制。它们可以自动地在不再需要时释放内存,从而避免内存泄漏和悬挂指针的问题。 shared_ptr是一种引用计数智能指针,它可以跟踪有多少个shared_ptr指向同一个对象,并在没有引用时自动释放内存。当创建shared_ptr时,它会增加引用计数,当销毁或重置shared_ptr时,它会减少引用计数。只有当引用计数为0时,才会真正释放内存。\[1\]shared_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建,也可以使用std::make_shared函数来创建。\[2\] unique_ptr是一种独占智能指针,它拥有对动态分配对象的唯一所有权。当unique_ptr被销毁时,它会自动释放内存。unique_ptr不能被复制,但可以通过std::move函数进行转移所有权。\[3\]unique_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建。 weak_ptr是一种弱引用智能指针,它指向由shared_ptr管理的对象,但不会增加引用计数。weak_ptr可以用于解决shared_ptr的循环引用问题,因为它不会导致对象无法释放。\[1\]weak_ptr可以通过shared_ptr的构造函数来创建。 auto_ptr是C++11之前的一种智能指针,它类似于unique_ptr,但有一些限制和问题。auto_ptr在复制时会转移所有权,这可能导致悬挂指针的问题。因此,auto_ptr已经被unique_ptr取代,不推荐使用。 总结来说,shared_ptr是引用计数智能指针,unique_ptr是独占智能指针weak_ptr是弱引用智能指针,而auto_ptr是已经过时的智能指针。它们各自有不同的用途和特点,可以根据具体的需求选择使用。 #### 引用[.reference_title] - *1* *2* *3* [C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptrweak_ptr](https://blog.csdn.net/weixin_44120785/article/details/128714630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值