cocos2d-x 3.1 autorelease机制理解

假设我们创建一个sprite的对象,sprite的create函数是这样写的

  1. Sprite* Sprite::create()  
  2. {  
  3.     Sprite *sprite = new (std::nothrow) Sprite();  
  4.     if (sprite && sprite->init())  
  5.     {  
  6.         sprite->autorelease();  
  7.         return sprite;  
  8.     }  
  9.     CC_SAFE_DELETE(sprite);  
  10.     return nullptr;  
我们看到这个sprite调用了autorelease方法,那么这个sprite就被放入到了autorelease池中。调用这个方法的话这个对象的生命周期就可以由引擎来控制了。 那么引擎是怎样自动控制这个对象的生命周期的呢?请继续往下看

sprite的父类Ref中有一个变量叫做_referenceCount,这个成员变量就是这篇文章的关键点了,这个变量叫做“引用计数”。cocos2d-x就是用这个叫做引用计数的东东来实现自动控制对象的生命周期的。引用计数在Ref的构造函数中被置为1。在cocos2d-x 3.1的导演类中我们可以看到这样一段代码,这段代码在每一帧都会被调用。


  1. void DisplayLinkDirector::mainLoop()  
  2. {  
  3.     if (_purgeDirectorInNextLoop)  
  4.     {  
  5.         _purgeDirectorInNextLoop = false;  
  6.         purgeDirector();  
  7.     }  
  8.     else if (! _invalid)  
  9.     {  
  10.         drawScene();  
  11.        
  12.         // release the objects  
  13.         PoolManager::getInstance()->getCurrentPool()->clear();  
  14.     }  
  15. }  

当我们创建完了这个sprite对象的的时候,这个函数就会走到下面 PoolManager::getInstance()->getCurrentPool()->clear(); 这个语句。 

跳转的clear函数的定义:

  1. void AutoreleasePool::clear()  
  2. {  
  3.     for (const auto &obj : _managedObjectArray)  
  4.     {  
  5.         obj->release();  
  6.     }  
  7.     _managedObjectArray.clear();  
  8. }  
这个时候就会遍历所有被加入过autorelease池的对象,并且运行release函数,下面是Ref的release函数的定义

  1. void Ref::release()  
  2. {  
  3.     CCASSERT(_referenceCount > 0, "reference count should greater than 0");  
  4.     --_referenceCount;  
  5.   
  6.     if (_referenceCount == 0)  
  7.     {  
  8.         delete this;  
  9.     }  
  10. }  
这段代码大家都看得懂吧,简洁明了:引用计数减1,如果减到0了,就删除。

总结一下刚才的流程:

1 创建sprite,此时引用计数为1,将这个sprite对象放入到autorelease池;

2 创建结束,导演类调用mainloop的时候遍历所有autorelease池中的对象,调用对象的release方法,引用计数减1,如果为零,就删除。

哈哈你特么的一定是在逗我,我刚创建出来就删除了,我的对象没了?又变成单身狗了吗?

淡定,请听我说。

我们创建出来sprite是不是没有addchild?没有addchild是不是会被删除?(他说的好有道理,我竟无言以对。。。)

在sprite被addchild的时候,会调用retain方法,这个时候,引用计数会加1,这个时候引用计数就变成了2,在mainloop的时候减1,就是1,而不是零,所以这个时候就不会被删除。

需要注意的是

1:mainloop函数中的 PoolManager::getInstance()->getCurrentPool()->clear();这句只会在对象被创建完了之后被调用一次。

2 我们可以通过对引用计数的操作来实现对象的生命周期进行控制,比如手动调用retain和release,关于怎么操作,这就在下一篇文章里面说吧。

3 初次写心得,有什么写得不好的请多多指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值