457
技術社區[雲棲]
從CCObject看cocos2d-x的內存管理機製
再看CCObject,剔除上節的拷貝相關,以及Lua腳本相關的屬性和方法後,CCObject還剩下什麼?
1.剩下什麼?
可以看到整個CCObject就是圍繞著m_uReference和m_uAutoReleaseCount在轉。這兩個變量的解釋如下。所以CCObject剩下的其實就是對內存的管理。
- CCObject::CCObject(void)//構造函數
- : m_nLuaID(0)
- , m_uReference(1) //引用計數,初始為1,當引用計數=0,自動釋放該對象
- , m_uAutoReleaseCount(0)//自動釋放對象計數,如果是手動new的,則為0,如果autoRelease的,則在AutoreleasePool會+1
- //這裏是保護成員,所以CCAutoreleasePool被聲明為友元類
- {
- static unsigned int uObjectCount = 0;//靜態成員,對象的計數,隻增不減,用於標識唯一一個對象實例
- m_uID = ++uObjectCount;
- }
- CCObject::~CCObject(void)
- {
- if (m_uAutoReleaseCount > 0)//如果是自動管理,則在PoolManager中刪除
- {
- 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);
- }
- }
- }
- void CCObject::release(void)//引用計數-1,如果引用計數=0,釋放對象
- {
- CCAssert(m_uReference > 0, "reference count should greater than 0");
- --m_uReference;
- if (m_uReference == 0)
- {
- delete this;
- }
- }
- void CCObject::retain(void)//引用計數+1,防止被對象釋放
- {
- CCAssert(m_uReference > 0, "reference count should greater than 0");
- ++m_uReference;
- }
- CCObject* CCObject::autorelease(void)//對象加入PoolManager,自動管理
- {
- CCPoolManager::sharedPoolManager()->addObject(this);
- return this;
- }
- bool CCObject::isSingleReference(void) const //返回是否唯一引用
- {
- 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) //輔助對象執行動作
- {
- visitor.visitObject(this);
- }
2.內存管理
從CCObject可以看出,內存的管理方式有兩種:手動管理和自動管理。
2.1.手動內存管理
想必從Java轉到C++的朋友可能很受不了C++再申請完內存後還要手動釋放,就像我從C++轉Java時也同樣很不習慣竟然不用管理內存,老是害怕會不小心讓係統給銷毀了。CCObject的成員變量m_uAutoReleaseCount標識了是手動管理還是自動管理。如果執行以下操作:
- CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1
- obj->release();//m_uReference-1後為0,執行delete this;
2.2.自動內存管理
如果需要進行內存的自動管理,那要怎麼做呢?
- CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1
- obj->autorelease();//m_uAutoReleaseCount=1,m_uReference=1
好了,什麼都不用做,obj自生自滅了。
如果我們需要隨時用到obj,而不願意讓它在我們不知情的情況下被釋放,那麼使用:
- obj->retain();//m_uAutoReleaseCount=1,m_uReference=2
- obj->release();//m_uAutoReleaseCount=1,m_uReference=1
又恢複回去了,所以,retain和release是好基友,一般在自動內存管理使用。
2.3.一個疑問
平時我們可能會這麼用:
- //CTestLayer.h
- class CTestLayer : public cocos2d::CCLayer
- {
- public:
- virtual bool init();
- CREATE_FUNC(CTestLayer);
- virtual void update(float delta);
- private:
- CCSprite* background;
- };
- //CTestLayer.cpp
- bool CTestLayer::init()
- {
- if ( !CCLayer::init() )
- {
- return false;
- }
- background=CCSprite::create("background.png");
- this->addChild(background);
- this->scheduleUpdate();
- return true;
- }
- void update(float delta)
- {
- background->setPositionY(background->getPositionY()-0.1);
- }
- this->addChild(background);
至於為什麼,大家翻一下addChild實現源碼就知道啦~
最後更新:2017-04-03 12:56:33