Cocos2d-x 的内存管理(10)
public:
Enemy() {}
~Enemy() {}
};
class EnemyManager
{
public:
EnemyManager() {}
~EnemyManager() {}
void RemoveEnemies() {
for (auto it : enemies_) {
delete *it;
}
}
private:
vector<Enemy*> enemies_;
};
刚开始的时候, 这只是一段和Cocos2d-x完全没有关系的代码, 并且运行良好, 有一天, 我感觉的Enmey其实是个Sprite就方便操作了. 将Enemy改为继承自Sprite, 那么这段代码就没有那么安全了, 因为EnemyManager在完全不知道enemy的引用计数的情况下, 使用delete删除了enmey, 假如此时还有其他地方对该enemy有引用, 就会crash. 虽然表面上看来是想添加一些CCSprite的显示功能, 但是实际上, 一入此门(从CCObject继承过来), 引用计数就已经无处不在, 此时需要把直接的delete改为调用release函数.
内存池
cocos2d-x起始也模拟了objc中的内存池, 但是因为不可能改变语言本身的特性, 那种简单的语法糖语法就没有, 需要的时候, 老实的操作CCPoolManager和CCAutoreleasePool吧. 在通常情况下, cocos2d-x增加的机制使得我们不太需要像在objc中那样使用内存池. 我来解释一下:
在cocos2d-x中, 几乎所有有意义的类都有create函数, 比如Sprite的create函数:
CCSprite* CCSprite::create()
{
CCSprite *pSprite = new CCSprite();
if (pSprite && pSprite->init())
{
pSprite->autorelease();
return pSprite;
}
CC_SAFE_DELETE(pSprite);
return NULL;
}
基本只干两个事情, 一个是new和init, 一个就是调用autorelease函数讲sprite本身加入内存池了. 此时讲sprite加入内存池后, sprite的所有权已经属于内存池了, 我们返回的指针其实是没有所有权的. 在create出一个类似对象后, 我们接下来的操作往往是吧这个对象再添加到parent node中(比如上层的scene或layer), 此时由内存池和这个parent node共同拥有这个sprite, 当sprite不需要再显示的时候, 直接通过removeChild将sprite从父节点中移除后, 就回到仅属于内存池的情况了.
在objc中, 要是都是上面的情况, 我们又不手动的清理内存池, 这其实就已经有内存泄漏了, 但是cocos2d-x实际是每帧都帮我们清理内存池的. 也就是说, 每一帧仅仅属于内存池的对象都会被释放. 见下面的代码:
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene();
// release the objects
CCPoolManager::sharedPoolManager()->pop();
相关新闻>>
- 发表评论
-
- 最新评论 更多>>