假如没有 AutoreleasePool 代码应该是这样的:
CCSprite *sprite = CCSprite:create() // new CCSprite() node->addChild(sprite); sprite->release(); // 必须放在addChild之后。
没有了 AutoreleasePool,cocos2d-x也可以工作,不讨论AutoreleasePool的意义。
AutoreleasePool 让sprite(设置了autorelease)的生命周期多了一个托管者(只托管一次)。
addChild等操作会retain一次对象,假如不retain,这个代码范围之后,sprite将被 release 并 delete;
对应的removeChild会release一次对象
引用计数可以告诉 AutoreleasePool 是否 delete 对象,但引用计数的意义不止如此?
PoolManager 管理 AutoreleasePool
class CC_DLL PoolManager { AutoreleasePool *getCurrentPool() const; std::vector<AutoreleasePool*> _releasePoolStack; };
class CC_DLL AutoreleasePool { void addObject(Ref *object); void clear(); bool contains(Ref* object) const; void dump(); }
AutoreleasePool 的实现会让大牛觉得不屑;
void DisplayLinkDirector::mainLoop() { ... PoolManager::getInstance()->getCurrentPool()->clear(); }
直接看clear
void AutoreleasePool::clear() { for (const auto &obj : _managedObjectArray) { obj->release(); } _managedObjectArray.clear(); // 留意这里,这里清空了 }
可以看到,遍历并release并清空
所以一开始 _managedObjectArray.reserve(150); 已经足够。
关注 _managedObjectArray
void AutoreleasePool::addObject(Ref* object) { _managedObjectArray.push_back(object); }
见CCObject(3.0换成了Ref)
Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addObject(this); return this; }
这就是 autorelease 的意义
以Speed动作对象为例
Speed* Speed::create(ActionInterval* action, float speed) { Speed *ret = new (std::nothrow) Speed(); if (ret && ret->initWithAction(action, speed)) { ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr; }
AutoreleasePool autorelease 等和 引用计数有点关系。