中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Cocos2d-x 注意隱藏的retain 內存管理

發布時間:2020-08-06 02:12:50 來源:網絡 閱讀:968 作者:杜甲同學 欄目:游戲開發

Cocos2d-x中的CCObject類及其派生類,使用autorelease()方法,將自身交托于CCPoolManager管理器進行管理,都可以使用retain()方法來使自身的引用計數加一,使用release()方法來使自身的引用計數減一,當引用計數為0的時候,CCPoolManager管理器就會將其刪除釋放。

所有實例化Cocos2d-x里面的以CCObject為基類的類時,都要使用其create()方法來創建對象,對于自己添加的派生類,需要通過CREATE_FUNC宏來實現create()方法,下面以《如何制作一個橫版格斗過關游戲 Cocos2d-x 2.0.4》來舉例介紹:
Hero.h

1
2
3
4
5
6
7
8
9

class Hero : public ActionSprite
{
public:
   Hero(void);
   ~Hero(void);

   CREATE_FUNC(Hero);
//……
};
若是需要create()方法帶有參數的話,仿造CREATE_FUNC的定義來實現,CREATE_FUNC宏定義如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
   __TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
   { \
       pRet->autorelease(); \
return pRet; \
   } \
else \
   { \
delete pRet; \
       pRet = NULL; \
returnNULL; \
   } \
}
具體可以類似如下:
SimpleDPad.h
1
2
3
4
5
6
7
8
9
10

class SimpleDPad : public cocos2d::CCSprite, public cocos2d::CCTargetedTouchDelegate
{
public:
   SimpleDPad(void);
   ~SimpleDPad(void);

static SimpleDPad* dPadWithFile(cocos2d::CCString *fileName, float radius);
bool initWithFile(cocos2d::CCString *filename, float radius);
//……
};
其中dPadWithFile靜態方法就是仿造的create()方法,具體實現如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

SimpleDPad* SimpleDPad::dPadWithFile(CCString *fileName, float radius)
{
   SimpleDPad *pRet = new SimpleDPad();
if (pRet && pRet->initWithFile(fileName, radius))
   {
       pRet->autorelease();
return pRet;
   }
else
   {
delete pRet;
       pRet = NULL;
returnNULL;
   }
}
當然這里的方法名可以改為以create開頭方便統一。
變量
當create出來的變量,被addChild到以CCNode為基類的類時,或者被addObject到CCArray、CCSet等時,都會自動將這個變量對象retain()一次,以防止被自動釋放導致的野指針問題,所以一般情況都不需要再手動調用retain()方法了。對于類定義中用CC_SYNTHESIZE_RETAIN宏聲明的變量,或者對臨時變量手動調用了retain()方法,一般都需要在析構函數或者特定的函數進行手動調用release()方法,類似如下:
GameLayer.h
1
2
3
4
5
6
7
8
9
10

class GameLayer : public cocos2d::CCLayer, public SimpleDPadDelegate
{
public:
   GameLayer(void);
   ~GameLayer(void);

   CREATE_FUNC(GameLayer);
//……
   CC_SYNTHESIZE_RETAIN(cocos2d::CCArray*, _robots, Robots);
};
GameLayer.cpp
1
2
3
4
5
6
7
8
9
10
11

GameLayer::GameLayer(void)
{
//……
   _robots = NULL;
}

GameLayer::~GameLayer(void)
{
//……
   CC_SAFE_RELEASE_NULL(_robots);
}
但是有一種特殊情況,類與變量的互相retain(),導致無法釋放,內存泄露。
ActionSprite.h
1
2
3
4
5
6
7
8
9

class ActionSprite : public cocos2d::CCSprite
{
public:
   ActionSprite(void);
   ~ActionSprite(void);

//……
   CC_SYNTHESIZE_RETAIN(cocos2d::CCAction*, _attackAction, AttackAction);
};
Hero.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13

bool Hero::init()
{
bool bRet = false;
do
   {
//……
this->setAttackAction(CCSequence::create(CCAnimate::create(attackAnimation), CCCallFunc::create(this, callfunc_selector(Hero::idle)), NULL));

//……
   } while (0);

return bRet;
}  
_attackAction變量以CCSequence類創建,CCSequence創建包含CCCallFunc的創建,CCCallFunc創建的時候將this指針傳遞下去,跟蹤源碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

CCCallFunc * CCCallFunc::create(CCObject* pSelectorTarget, SEL_CallFunc selector)
{
   CCCallFunc *pRet = new CCCallFunc();

if (pRet && pRet->initWithTarget(pSelectorTarget)) {
       pRet->m_pCallFunc = selector;
       pRet->autorelease();
return pRet;
   }

   CC_SAFE_DELETE(pRet);
returnNULL;
}

bool CCCallFunc::initWithTarget(CCObject* pSelectorTarget) {
if (pSelectorTarget)
   {
       pSelectorTarget->retain();
   }

if (m_pSelectorTarget)
   {
       m_pSelectorTarget->release();
   }

   m_pSelectorTarget = pSelectorTarget;
returntrue;
}
可以看到它對this指針的對象進行retain()調用,導致Hero對象無法被自動釋放,需要先手動對_attackAction變量進行release()調用,CCCallFunc將進行析構,進而將會對this指針的對象進行release()調用
1
2
3
4

virtual ~CCCallFunc()
{
   CC_SAFE_RELEASE(m_pSelectorTarget);
}
解決方法舉例如下:
ActionSprite.h
1
2
3
4
5
6

class ActionSprite : public cocos2d::CCSprite
{
public:
//……
  virtual void cleanup();
};  
ActionSprite.cpp
1
2
3
4
5
6
7
8

void ActionSprite::cleanup()
{
   CC_SAFE_RELEASE_NULL(_idleAction);
   CC_SAFE_RELEASE_NULL(_attackAction);
   CC_SAFE_RELEASE_NULL(_walkAction);
   CC_SAFE_RELEASE_NULL(_hurtAction);
   CC_SAFE_RELEASE_NULL(_knockedOutAction);

   CCSprite::cleanup();
}  
最后用Visual Leak Detector和DevPartner檢測,均未檢測到內存泄露。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

屯留县| 甘南县| 闽清县| 牟定县| 鹤壁市| 赣榆县| 巴彦淖尔市| 清水县| 威海市| 酒泉市| 浠水县| 昌黎县| 鱼台县| 洪洞县| 施秉县| 彰武县| 六安市| 泰安市| 永平县| 黄大仙区| 卢湾区| 衡山县| 英山县| 商丘市| 班戈县| 宜黄县| 静海县| 荣成市| 吴江市| 灵寿县| 蓬安县| 蓬莱市| 车险| 贵阳市| 如皋市| 富平县| 中山市| 东城区| 邛崃市| 北川| 乐平市|