do{}while(0)与CC_BREAK_IF的绝妙搭配
2014-10-19 11:57
429 查看
从一开始觉得没有必要,到觉得非常好用,我经历了大概两个月的时间,下面来总结一下什么情况下使用这种结构吧。
第一种情况:当加载文件的时候,如果加载文件失败,需要报错的时候。
当前,可以用try{}catch(){}finally{}这种结构,但是这样做会极大的增加编译后文件的大小,使用do{}while(0)加上CC_BREAK_IF就能实现一样的效果,而且不增加文件的大小。
下面是一个例子:
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)->getComponent("GUIComponent"));
SelectPeopleUI = SelectPeople->getNode();
this->setCampBtn();
return true;
}while(0);
CCLOG("ERROR:Load Resources Fail in GameScene::setScene");
return false;
}
如果在中途出现任何一个变量执行后还是nullptr,那么就CC_BREAK_IF,然后显示错误日志,最后返回false给上层函数进行处理。这样的处理方式是不是既优雅又方便快速,又避免了可能错误使用空指针。
第二种情况:当无论如何都需要在函数最后进行清理操作的时候。
下面举一个比较典型的例子,就是在函数开头声明了一个new的指针(非智能指针),按照正常的流程,需要delete,但是我们无法保证程序会不会在中途就return了,因为后续的维护者并不知道还有这个清除操作需要执行,下面是一个对比例子:
//error
void test()
{
GameScene* gamescene = new GameScene;
// doSomething...
if(gamescene->getChildByTag(111) == nullptr)
{
return;
}
// doSomething...
delete gamescene;
gamescene = nullptr;
}
//right
void test1()
{
GameScene* gamescene = new GameScene;
do{
// doSomething...
CC_BREAK_IF(gamescene->getChildByTag(111) == nullptr);
// doSomething...
}while(0);
delete gamescene;
gamescene = nullptr;
}
使用CC_BREAK_IF可以保证永远都会执行到最后两行,也就不会出现内存泄露。
但是这个组合也不是万能的,下面就说一个不适合这种结构的情况吧。当do{}while(0)的括号中存在循环的时候,就不适用这个组合了,因为break毕竟只能跳出一层循环,下面是一个例子:
void test2()
{
do{
for(int i = 0;i <5;++i)
{
// doSomething...
CC_BREAK_IF(i>4);
// doSomething...
}
CCLOG("永远显示这一行日志");
}while(0);
}
我们希望的是,CC_BREAK_IF能跳出do{}while(0)循环,但是实际上,只跳出了for循环,所以使用do{}while(0)和CC_BREAK_IF的时候,需要确保其内部不能存在其他循环,如果存在循环,还是建议使用try{}catch(){}
第一种情况:当加载文件的时候,如果加载文件失败,需要报错的时候。
当前,可以用try{}catch(){}finally{}这种结构,但是这样做会极大的增加编译后文件的大小,使用do{}while(0)加上CC_BREAK_IF就能实现一样的效果,而且不增加文件的大小。
下面是一个例子:
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)->getComponent("GUIComponent"));
SelectPeopleUI = SelectPeople->getNode();
this->setCampBtn();
return true;
}while(0);
CCLOG("ERROR:Load Resources Fail in GameScene::setScene");
return false;
}
如果在中途出现任何一个变量执行后还是nullptr,那么就CC_BREAK_IF,然后显示错误日志,最后返回false给上层函数进行处理。这样的处理方式是不是既优雅又方便快速,又避免了可能错误使用空指针。
第二种情况:当无论如何都需要在函数最后进行清理操作的时候。
下面举一个比较典型的例子,就是在函数开头声明了一个new的指针(非智能指针),按照正常的流程,需要delete,但是我们无法保证程序会不会在中途就return了,因为后续的维护者并不知道还有这个清除操作需要执行,下面是一个对比例子:
//error
void test()
{
GameScene* gamescene = new GameScene;
// doSomething...
if(gamescene->getChildByTag(111) == nullptr)
{
return;
}
// doSomething...
delete gamescene;
gamescene = nullptr;
}
//right
void test1()
{
GameScene* gamescene = new GameScene;
do{
// doSomething...
CC_BREAK_IF(gamescene->getChildByTag(111) == nullptr);
// doSomething...
}while(0);
delete gamescene;
gamescene = nullptr;
}
使用CC_BREAK_IF可以保证永远都会执行到最后两行,也就不会出现内存泄露。
但是这个组合也不是万能的,下面就说一个不适合这种结构的情况吧。当do{}while(0)的括号中存在循环的时候,就不适用这个组合了,因为break毕竟只能跳出一层循环,下面是一个例子:
void test2()
{
do{
for(int i = 0;i <5;++i)
{
// doSomething...
CC_BREAK_IF(i>4);
// doSomething...
}
CCLOG("永远显示这一行日志");
}while(0);
}
我们希望的是,CC_BREAK_IF能跳出do{}while(0)循环,但是实际上,只跳出了for循环,所以使用do{}while(0)和CC_BREAK_IF的时候,需要确保其内部不能存在其他循环,如果存在循环,还是建议使用try{}catch(){}
相关文章推荐
- do{}while(0)与CC_BREAK_IF的绝妙搭配
- do{}while(0)与CC_BREAK_IF的绝妙搭配
- Cocos2D-x中关于do{}while(0)和CC_BREAK_IF的用法
- cocos2d-x系列笔记技巧篇(1)---关于do{}while(0)和CC_BREAK_IF的用法
- Cocos2D-x中关于do{}while(0)和CC_BREAK_IF的用法
- Cocos2D-x中关于do{}while(0)和CC_BREAK_IF的用法
- 笔记:循环(for, if, do...while, break, switch)
- shell编程--流程控制for,do-while,if-then,break,continue,case等
- shell编程--流程控制for,do-while,if-then,break,continue,case等
- [置顶] 循环语句if(){}else{}、if(){}else if(){}...else{}、do{}while()、for(){}、with(){}break/continue语句
- 流程控制:if...else,while..do,foreach,contiue,break;
- if ,swith,for,while,do/while,break,contine的简单说明
- C语言中流程控制语句(if,switch,for,while,do-while,continue,break,return)
- if,continue,break,while,do-while, switch,return,foreach,for等条件语句的使用
- C语言学习3:if ,for,do..while,continue和break,goto,swtich,输入输出缓存区,随机数产生
- 黑马程序员——选择结构if、switch,循环结构while、do-while、for
- c++学习 day2 循环学习(while do while for) 分支学习(if ; if else; if else if; switch的应用 )
- linux shell awk 流程控制语句(if,for,while,do)详细介绍
- 3.[do...while]+[switch]+[break]+[continue]
- js---javaScript(循环语句的使用实例)for while do....while(转移语句): break, continue , return