在这里要先明白cocos2d-x内存管理的来源。因为cocos2d-x是将cocos2d重写了一遍,内存管理也是和cocos2d一样,通过引用计数来控制。其实现是在cocos2d-x的基类CCObject中,所以要弄懂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
//在内存回收池的引用次数,也就是调用一次autorelease这个值加1
unsigned int m_uAutoReleaseCount;
public:
//构造
CCObject(void);
/**
* @lua NA
*/
//析构
virtual ~CCObject(void);
//引用计数减一,为0回收内存
void release(void);
//引用计数加1
void retain(void);
//把当前对象加入到内存回收池中
CCObject* autorelease(void);
//拷贝
CCObject* copy(void);
//是否单引用
bool isSingleReference(void) const;
//返回当前的引用计数
unsigned int retainCount(void) const;
//是否是同一个对象
virtual bool isEqual(const CCObject* pObject);
//实现观察者观察CCObject对象
virtual void acceptVisitor(CCDataVisitor &visitor);
//更新
virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
//声明CCAutoreleasePool为友元类
friend class CCAutoreleasePool;
};
再看其实现:
CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // 当对象被创建时,应用计数初始化为1,这样便能保证该对象至少能存活一帧
, m_uAutoReleaseCount(0)
{
static unsigned int uObjectCount = 0;
m_uID = ++uObjectCount;//与脚本相关,略过
}
CCObject::~CCObject(void)
{
// if the object is managed, we should remove it
// from pool manager
if (m_uAutoReleaseCount > 0)//如果当该对象被销毁时,仍存在于内存回收池中,那么内存回收池清掉该对象
{
CCPoolManager::sharedPoolManager()->removeObject(this);
}
// if the object is referenced by Lua engine, remove it
//下面与脚本引擎相关,略过
if (m_nLuaID)
{
CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(this);
}
else
{
CCScriptEngineProtocol* pEngine = CCScriptEngineManager::sharedManager()->getScriptEngine();
if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript)
{
pEngine->removeScriptObjectByCCObject(this);
}
}
}
CCObject* CCObject::copy()
{
//拷贝,空实现
return copyWithZone(0);
}
void CCObject::release(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
//引用计数减1
--m_uReference;
if (m_uReference == 0)//如果引用计数为0,则删除该对象
{
delete this;
}
}
void CCObject::retain(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
//引用计数加1
++m_uReference;
}
CCObject* CCObject::autorelease(void)
{
//加入到自动回收池中
CCPoolManager::sharedPoolManager()->addObject(this);
return this;
}
bool CCObject::isSingleReference(void) const
{
//若果引用计数为1,则表明当前对象是单引用
return m_uReference == 1;
}
unsigned int CCObject::retainCount(void) const
{
//返回引用计数
return m_uReference;
}
bool CCObject::isEqual(const CCObject *pObject)
{
//判断是否是同一个对象
return this == pObject;
}
void CCObject::acceptVisitor(CCDataVisitor &visitor)
{
//调用观察者的visitObject观察该对象
visitor.visitObject(thi