Cocos2d-x 内存管理机制
- By Scarb
- Scarb’s Blog
- 对Cocos2d-x的内存管理机制,之前一直不是很清楚。现在算是清楚多了,记一下笔记。
1. 引用计数
Cocos2d-x 所有对象几乎都继承自Ref基类,该基类主要进行引用计数管理。
public:
void retain();
void release();
Ref* autorelease();
unsigned int getReferenceCount() const;
protected:
Ref();
protected:
/// count of references
unsigned int _referenceCount;
friend class AutoreleasePool;
当一个对象由new
分配内存时,引用计数为1,调用retain()
会增加引用计数,调用release()
减少引用计数。
release()
方法会在引用计数为0时调用delete删除对象并释放内存。
retain()
方法在默认的create()
函数中被自动调用。
在仅有引用计数的情况下管理UI元素的示例:
auto node = new Node(); // 引用计数为1
addChild(node); // 引用计数为2
// .......
node->removeFromParent(); // 引用计数为1
node->release(); // 引用计数为0,对象被删除
2. 用autorelease()方法声明一个“智能指针”
Cocos2d-x 使用autorelease()
方法来声明一个对象的指针为智能指针。
这些智能指针全部被加入一个AutoreleasePool
中,在每一帧结束的时候对加入AutoreleasePool
中的对象进行清理。
也就是说一个智能指针的生命周期是从被创建开始,到当前帧结束时结束。
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
在以上方法中,Cocos2d-x通过autorelease()
方法将一个对象添加到AutoreleasePool
中。
并在每一帧结束的时候清理当前AutoreleasePool
中的对象:
void DisplayLinkDirector::mainLoop()
{
if(! _invalid)
{
drawScene();
// release the object
PoolManager::getInstance()->getCurrentPool()->clear();
}
}
void AutoreleasePool::clear()
{
for(const auto &obj : _manageedObjectArray)
{
obj->release();
}
_manageObjectArray.clear();
}
AutoreleasePool
对池中的每个对象执行一次release()
操作,假设该对象的引用计数为1,表示其从未被使用,则执行release()
操作之后引用计数为0,对象将被释放。
创建一个不被使用的Node
如下:
auto node = new Node(); // 引用计数为1
node->autorelease(); // 加入智能指针池
该帧结束的时候Node
对象将被自动释放。
如果在释放之前被使用
auto node = new Node(); // 引用计数为1
node->autorelease(); // 加入智能指针池
addChild(node); // 引用计数为2
该帧结束后AutoreleasePool
对其进行1次release()
操作之后,引用计数为1,该对象继续存在。
当下次该Node
被移除的时候,引用计数为0,对象被自动释放。
此时该AutoreleasePool
中的所有对象已经被移出,没有被释放的对象引用为1,继续存在。当remove
该对象或者该对象的父节点被remove
时,都会release
该对象。
Cocos2d-x 使用静态的create()
方法返回一个智能指针对象。同时自定义的UI元素也应该遵循这样的风格。
Node* Node::create()
{
Node *ret = new Node();
if (ret && ret->init())
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}
3. 参考资料
- 《我所理解的Cocos2d-x》——秦春林