c++ 智能指针- shared_ptr和weak_ptr

本文探讨c++中智能指针shared_ptr和weak_ptr的原理及应用场景,解释如何避免循环引用导致的内存泄露,并讨论enable_shared_from_this的正确使用方式,以增强对c++内存管理的理解。
摘要由CSDN通过智能技术生成

c++中智能指针的作用是非常大的,它不仅能解决很多裸指针带来的内存相关问题,还能用来管理资源(RAII)。

c++中的智能指针有很多种,其中以shared_ptr和weak_ptr最为重要(个人观点),掌握了这两个智能指针的原理,其它的就很好理解了。


shared_ptr是典型的引用计数型智能指针,相信很多c++程序员都写过功能类似的智能指针类。很多时候用这个指针就足够了。

但是有些情况下,shared_ptr可能产生循环引用, 比如Observer模式中,或者父子关系的对象等。为了解决循环引用而造成的内存泄露,引入了weak_ptr。

shared_ptr是strong reference, weak_ptr是weak reference。shared_ptr保证所持有的raw指针是有效的,而weak_ptr则不能保证所持有的指针是否还指向一个有效的对象。

在需要访问所持有的指针的时候,调用weak_ptr的expired或者lock就能判断出是否能得到对应的shared_ptr。


本文的目的不是为了介绍shared_ptr和weak_ptr的使用方法,而是为了介绍它们的实现原理,更主要的是为了说明weak_ptr是如何知道是否还有shared_ptr对象存在的。

还有一些关于它们使用习惯或注意点的说明。


一、shared_ptr

  • ref_count / control block (控制块)

在典型的实现中,std::shared_ptr 只保存两个指针:

  • 指向被管理对象的指针
  • 指向控制块(control block)的指针

控制块是一个动态分配的对象,其中包含:

  • 指向被管理对象的指针或被管理对象本身
  • 删除器
  • 分配器(allocator)
  • 拥有被管理对象的 shared_ptr 的数量
  • 引用被管理对象的 weak_ptr 的数量

通过 std::make_shared 和 std::allocate_shared 创建 shared_ptr 时,控制块将被管理对象本身作为其数据成员;而通过构造函数创建 shared_ptr 时则保存指针。


我们可以通过阅读代码来了解它的具体实现,VS2010的实现是: memory , 这个实现的可读性还是不错的。
(注意:gcc的实现可能和这个不同,即使VS的不同版本之间的实现也可能不同,但原理类似。)
  
  
  
class _Ref_count_base { // common code for reference counting
private:
virtual void _Destroy () = 0 ;
virtual void _Delete_this () = 0 ;

long _Uses ;
long _Weaks ;

protected:
_Ref_count_base () : _Uses ( 1 ), _Weaks ( 1 ) { // construct
}
...
};
    
    
    
template < class _Ty > class _Ref_count : public _Ref_count_base {
};
template < class _Ty , class _Dx > class _Ref_count_del : public _Ref_count_base {
};
    
    
    
template < class _Ty ,
class _Dx ,
class _Alloc >
class _Ref_count_del_alloc
: public _Ref_count_base {
};

template < class _Ty > class _Ptr_base { 
  ...
private:
  
  
  
_Ty * _Ptr ;
_Ref_count_base * _Rep ;
};

template < class _Ty class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值