do{}while(0)与CC_BREAK_IF的绝妙搭配

从一开始觉得没有必要,到觉得非常好用,我经历了大概两个月的时间,下面来总结一下什么情况下使用这种结构吧。

第一种情况:当加载文件的时候,如果加载文件失败,需要报错的时候。

当前,可以用try{}catch(){}finally{}这种结构,但是这样做会极大的增加编译后文件的大小,使用do{}while(0)加上CC_BREAK_IF就能实现一样的效果,而且不增加文件的大小。

下面是一个例子:

?
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
29
30
31
bool GameScene::setScene()
{
do {
auto node = SceneReader::getInstance()->createNodeWithSceneFile( "publish/GameScene.csb" );
CC_BREAK_IF(!node);
m_UI_Background->addChild(node);
auto Checkerboard = (Comrender*)(node->getChildByTag( 10009 )->getComponent( "GUIComponent" ));
CheckerboardUI = Checkerboard->getNode();
//设置按钮
m_btn_Setting = dynamic_cast<button*>(CheckerboardUI->getChildByName( "Button_Setting" ));
CC_BREAK_IF(!m_btn_Setting);
//音乐按钮
m_btn_Music = dynamic_cast<button*>(CheckerboardUI->getChildByName( "Button_Music" ));
CC_BREAK_IF(!m_btn_Music);
//棋盘锁
m_btn_Lock = dynamic_cast<button*>(CheckerboardUI->getChildByName( "Button_Lock" ));
CC_BREAK_IF(!m_btn_Lock);
//棋盘图片
m_Image_Checkerboard = dynamic_cast<imageview*>(CheckerboardUI->getChildByName( "Image_Checkerboard" ));
CC_BREAK_IF(!m_Image_Checkerboard);
m_Checkerboard = Checkerboard::create(m_Image_Checkerboard);
auto SelectPeople = (Comrender*)(node->getChildByTag( 10031 ));
SelectPeopleUI = SelectPeople->getNode();
this ->setCampBtn();
return true ;
} while ( 0 );
cclOG( "ERROR:Load Resources Fail in GameScene::setScene" );
false ;
}</imageview*></button*></button*></button*>

如果在中途出现任何一个变量执行后还是nullptr,那么就CC_BREAK_IF,然后显示错误日志,最后返回false给上层函数进行处理。这样的处理方式是不是既优雅又方便快速,又避免了可能错误使用空指针。


第二种情况:当无论如何都需要在函数最后进行清理操作的时候。

下面举一个比较典型的例子,就是在函数开头声明了一个new的指针(非智能指针),按照正常的流程,需要delete,但是我们无法保证程序会不会在中途就return了,因为后续的维护者并不知道还有这个清除操作需要执行,下面是一个对比例子:

?
26
//error
void test()
GameScene* gamescene = new GameScene;
// doSomething...
if (gamescene->getChildByTag( 111 ) == nullptr)
{
return ;
}
// doSomething...
delete gamescene;
gamescene = nullptr;
}
//right
test1()
{
GameScene;
{
// doSomething...
CC_BREAK_IF(gamescene->getChildByTag( ) == nullptr);
// doSomething...
);
delete gamescene;
gamescene = nullptr;
}

使用CC_BREAK_IF可以保证永远都会执行到最后两行,也就不会出现内存泄露。

但是这个组合也不是万能的,下面就说一个不适合这种结构的情况吧。当do{}while(0)的括号中存在循环的时候,就不适用这个组合了,因为break毕竟只能跳出一层循环,下面是一个例子:

12
test2()
for ( int i = ;i < 5 ;++i)
{
// doSomething...
CC_BREAK_IF(i> 4 );
// doSomething...
"永远显示这一行日志" );
);
我们希望的是,CC_BREAK_IF能跳出do{}while(0)循环,但是实际上,只跳出了for循环,所以使用do{}while(0)和CC_BREAK_IF的时候,需要确保其内部不能存在其他循环,如果存在循环,还是建议使用try{}catch(){}

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...