智能指针 -- 循环引用

C++最新标准C++11中已将基于引用计数的智能指针share_prt收入囊中,智能指针的使用门槛越来越低,不需要使用boost库,我们也能轻松享受智能指针给我们带来的方便。
智能指针,正如它的名字一样,似乎是个近乎完美的聪明角色,程序员不用再纠结于new出来的内存在哪释放比较合适这种问题。比如当一个资源被多个模块共享时,程序员需要在所有模块的生命周期都结束时,由最后一个不使用该指针的模块触发指针的释放行为,而模块的生命周期可能根本在写代码时就确定不了。
智能指针的出现,给不支持垃圾回收机制的C++带来了一丝曙光。下面简单介绍一下智能指针的运行机制:
当我们需要从堆上申请空间时,可以将new出来的指针交由智能指针管理,比如:shared_ptr a(new int);,这样当a出作用域时,在a对象析构的时候,就会释放持有的堆上指针,这是通过C++的析构函数实现的。
当一个智能指针对象拷贝赋值给另外一个智能指针时,比如shared_ptr b = a;a和b两个智能指针指向了同一块堆上的空间,a或b中的任意一个对象出作用域时,都不应该释放堆上的空间,因为还有另外一个智能指针对象在引用这个堆空间,于是就引入了引用计数机制来解决这个问题。当一个智能指针对象被创建时,会在堆上创建一个用于计数的空间,当shared_ptr b = a;执行后,b对象浅拷贝a对象的计数区指针,然后将计数区的值+1。这样就相当于拷贝赋值出的一组智能指针都指向同一块堆上的数据空间,同时还共享另外一块堆上计数区(这也是叫做shared_ptr的原因)。在智能指针对象析构时,不是简单的直接释放持有的堆数据空间,而是先将共享的引用计数-1,之后发现引用计数为0的话,才调用delete。

智能指针的实现思路也体现了C++基于对象的原则,对象应该为自己管理的资源负责,包括资源的分配与释放,而且最好将资源的释放与分配搞的自动化一点,典型的实现方法就是在构造函数里分配资源,在析构函数里释放资源,这样当其他程序员在使用这个对象时,该对象的资源问题几乎不用额外的操心,即优雅又方便。


好啦,我是华丽的分割线。下面进入本文的重点,当循环引用发生时,基于计数的共享机制将会被彻底击败。
一个简单的例子,分析见注释:(下面代码一运行,内存有泄漏)

#include <iostream>
#include <memory>
using namespace std;

class B;
class A
{
public:
    shared_ptr<B> m_b;
};

class B
{
public:
    shared_ptr<A> m_a;
};

int main()
{
    shared_ptr<A> a(new A);
    //new出来的A的引用计数此时为1
    shared_ptr<B> b(new B);
    //new出来的B的引用计数此时为1
    a->m_b = b; //B的引用计数增加为2
    b->m_a = a; //A的引用计数增加为2

/*b先出作用域,B的引用计数减少为1,不为0,
    所以堆上的B空间没有被释放,且B持有的A也没有机会被析构,A的引用计数也完全没减少

a后出作用域,同理A的引用计数减少为1,不为0,所以堆上A的空间也没有被释放*/
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值