假设我们创建一个sprite的对象,sprite的create函数是这样写的
- Sprite* Sprite::create()
- {
- Sprite *sprite = new (std::nothrow) Sprite();
- if (sprite && sprite->init())
- {
- sprite->autorelease();
- return sprite;
- }
- CC_SAFE_DELETE(sprite);
- return nullptr;
- }
sprite的父类Ref中有一个变量叫做_referenceCount,这个成员变量就是这篇文章的关键点了,这个变量叫做“引用计数”。cocos2d-x就是用这个叫做引用计数的东东来实现自动控制对象的生命周期的。引用计数在Ref的构造函数中被置为1。在cocos2d-x 3.1的导演类中我们可以看到这样一段代码,这段代码在每一帧都会被调用。
- void DisplayLinkDirector::mainLoop()
- {
- if (_purgeDirectorInNextLoop)
- {
- _purgeDirectorInNextLoop = false;
- purgeDirector();
- }
- else if (! _invalid)
- {
- drawScene();
- // release the objects
- PoolManager::getInstance()->getCurrentPool()->clear();
- }
- }
当我们创建完了这个sprite对象的的时候,这个函数就会走到下面 PoolManager::getInstance()->getCurrentPool()->clear(); 这个语句。
跳转的clear函数的定义:
- void AutoreleasePool::clear()
- {
- for (const auto &obj : _managedObjectArray)
- {
- obj->release();
- }
- _managedObjectArray.clear();
- }
- void Ref::release()
- {
- CCASSERT(_referenceCount > 0, "reference count should greater than 0");
- --_referenceCount;
- if (_referenceCount == 0)
- {
- delete this;
- }
- }
总结一下刚才的流程:
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 初次写心得,有什么写得不好的请多多指正。