Cocos2d-x 3.x引用计数

引用计数:每一个对象都维护了一个 对象所有引用的计数值(表示有多少这个对象的引用,在堆内存中,只有一份该对象资源,但是由堆是共享的,那么该对象资源可以在其他函数内通过对象指针引用)。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

举例说明

这里写图片描述

如上图所示,我们在fun()函数中,通过Sprite::create(“xxx.png”)方式实例化一个Sprite对象,然后返回对象指针,由于采用create方式生成的过程中,会主动调用autorelease(),将sp指向的对象交由自动释放池(AutoreleasePool)管理,而默认的自动释放池也是一个堆上对象(new出来的),所以一般通过create方式创建的对象,实际只会在程序结束时才释放内存。那么既然create创建出来的对象会一直在堆内存之中,而堆是线程间共享的,所以只要能够获得对象指针,那么就可以在线程间访问该对象,自然不同函数之间也可以访问该对象。

源码分析

以下是摘自3.9版本的源码:

class Ref
{
public:
    Ref();
    ~Ref();

    void retain();

    void release();

    Ref* autorelease();
protected:
    friend class AutoreleasePool;
private:
    unsigned int m_referenceCount;
}

Ref::Ref()
{
    m_referenceCount = 1;//一个新的Ref对象,引用计数将初始化为1
}

Ref::~Ref()
{   //虽然create方式中,也是通过new创建的堆上对象,但是由于autorelease了,所以通过create创建的对象,不要自己主动调用delete来释放内存,如果想释放内存,可以调用release()。
}

void Ref::retain()
{
    ++m_referenceCount; 
}

void Ref::release()
{//release是能够做到安全的管理内存,只有当对象没有被引用时,才delete该对象。
    --m_referenceCount;
    if(m_referenceCount == 0)
    {
        delete this;
    }
}

void Ref::autorelease()
{
  PoolManager::getInstance()->getCurrentPool()->addObject(this);
    return this;
}

分析

  • Ref对象实例化的时候,引用计数将初始化为1,而析构函数中,并未将引用计数-1;为此,为了保证能正确管理内存。对于new 出来的 Ref 对象,如果调用了autorelease(),那么即使之前是new出来的,也不应该通过delete释放,因为autorelease()将本对象交由AutoreleasePool自动管理。

  • Autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该对象放入了当前的AutoreleasePool中,当该pool被释放时,该pool中的所有对象会被调用release。而默认的pool对象(默认只有一个pool)也是堆上对象。

  • 为了优化内存使用,当某个Ref对象只需要使用一次,那么就在该函数中实例化一个局部变量AutoreleasePool pool,那么当本函数结束时,根据局部变量的生命周期,pool将在函数结束后释放,并主动调用池中对象的release(),从而释放对象的内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值