最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
Cocos2d-x游戏开发实例详解5:神奇的自动释放
本系列将结合本人在游戏开发中的实际案例,详细讲解Cocos2d-x的相关知识。本篇将深入阐述Cocos2d-x中的内存自动释放机制。
内存自动回收并非新鲜概念,像Java的垃圾回收机制以及Objective-C的自动回收机制,都属于类似的概念。Cocos2d-x基于C++实现,其内存管理遵循C++的规则,即“谁创建,谁维护”。
为了与Cocos2d引擎保持一致,并降低学习难度,Cocos2d-x引入了内存自动释放机制,该机制主要基于引用计数和自动释放池实现。
从官方的Cocos2d-x类图可以得知,CCObject 是所有类的基类,自动释放机制正是在这个类中实现的。以下是 CCObject 类的定义:
class CC_DLL CCObject : public CCCopying
{
public:
// object id, CCScriptSupport need public m_uID
unsigned int m_uID;
// Lua reference id
int m_nLuaID;
protected:
// count of references
unsigned int m_uReference;
// count of autorelease
unsigned int m_uAutoReleaseCount;
public:
CCObject(void);
virtual ~CCObject(void);
void release(void);
void retain(void);
CCObject* autorelease(void);
CCObject* copy(void);
bool isSingleReference(void);
unsigned int retainCount(void);
virtual bool isEqual(const CCObject* pObject);
virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
friend class CCAutoreleasePool;
};
在上述代码中,m_uReference 变量就是引用计数器。
关键函数如下:
CCObject* CCObject::autorelease(void)
{
CCPoolManager::sharedPoolManager()->addObject(this);
return this;
}
从这段代码可以看出,当我们调用 autorelease 方法时,实际上是将当前对象添加到自动释放池中进行管理。至于自动释放池具体是什么,我们稍后再详细探讨。
接下来,我们看看引用计数是如何使用的。以下是 CCObject 类的构造函数:
CCObject::CCObject(void)
:m_uAutoReleaseCount(0)
,m_uReference(1) // when the object is created, the reference count of it is 1
,m_nLuaID(0)
{
static unsigned int uObjectCount = 0;
m_uID = ++uObjectCount;
}
在对象被创建时,其引用计数初始化为1,代码中的注释也明确说明了这一点。
再来看 retain 函数:
void CCObject::retain(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
++m_uReference;
}
这里有一个断言,用于检测引用计数是否大于0。在实际开发中,可能会有代码因为引用计数不满足条件而在此处停止执行。调用 retain 方法会使引用计数加1,但前提是引用计数必须大于0。这意味着,当调用 retain 方法时,对象必须处于有效状态。如果 m_uReference <= 0,说明对象已经被释放,此时不能再调用 retain 方法。
看完 retain 方法,再来看 release 方法,对于有iOS应用开发经验的开发者来说,应该对这个方法比较熟悉:
void CCObject::release(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
--m_uReference;
if (m_uReference == 0)
{
delete this;
}
}
从代码可以看出,release 方法的作用正如其名,即释放对象。如果引用计数大于0,调用 release 方法会将引用计数减1。当引用计数减到0时,对象会被 delete 掉。
需要注意的是,retain 和 release 这两个方法通常不需要手动调用,否则自动释放机制就失去了意义。
前面提到,若想实现对象的自动释放,可调用 autorelease 方法,示例如下:
CCObject *obj = new CCObject();
obj->autorelease();
通过以上内容,我们对Cocos2d-x的内存自动释放机制有了初步的了解。在实际开发中,合理运用这些机制可以有效避免内存泄漏问题。