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

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

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

当前,可以用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(){}

时间: 2024-10-11 23:00:19

do{}while(0)与CC_BREAK_IF的绝妙搭配的相关文章

cocos2dx中替代goto的用法:do{}while(0)和CC_BREAK_IF

我们时常会调用某个函数来创建一个对象,但由于内存不足或其他异常情况发生时对象可能会创建失败,创建失败我们就要结束当前程序转到错误处理地方去处理错误或释放已生成的对象. int* p1 = new int; CCObject* o1 = fun1(); if(!o1) goto catchcode; CCObject* o2 = fun2(); if(!o2) goto catchcode; //如果代码都执行成功 delete p; p = NULL; //如果o1 o2有发生错误 catchc

基于Smadja算法的搭配词自动提取

搭配词(collocation) 广义而言,搭配词(collocation)是指两个或多个词一招语言习惯性结合在一起表示某种特殊意义的词汇.搭配词在不同的研究领域上又不同的解读,尚未有一致性的定义.大概的意思就是词语的习惯搭配了,就是学英语时老师一直拿来搪塞我们的那种『习惯搭配』.比如sit in traffic,表示堵车或者在通勤上花费了非常多时间的意思,那么sit_traffic就是一个搭配词.其中sit称为base word,traffic称为collocate. 所以collocatio

校园商铺-4店铺注册功能模块-1Dao层之新增店铺

1. 系统功能开发的优先级. 项目共有3个系统,前端展示系统,店家管理系统,超级管理员管理系统. 店家的优先级是最高的,因为最有可能带来收益的是店家,而且一旦店家系统开发出来,店家往系统里填写商品信息.前端展示系统才有展示的数据源. 超级管理员系统可以用手工录入的方式来代替,优先级是最低. 分析之后,开发的优先级从高到低一次为店铺管理.前端展示.超级管理员系统. 2. 项目1.0-店家管理系统开发 店家可以通过店家管理系统来管理店铺信息 店铺 商品 2.1 店铺注册从底层到前端开发 学习目标:

嵌入式

作者:秋枫链接:https://www.zhihu.com/question/35134077/answer/62683025来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 去淘宝买小车底盘,可以用全直流的可以用直流+舵机的,买驱动板,然后用单片机做智能小车,加上各种传感器可以实现不同的功能,比如红外的,可以做避障,可以做寻迹,原理就是根据不同的红外传感器传回的有没有返回信号,哪些灯有信号,甚至是强弱来判断事件,单片机做出动作处理.红外遥控器非常便宜,只要知道协议

cocod2d-x 之 HelloWorld

cocos2d-x 2.2创建项目 进入cocos2d-x-2.2/tools/project-creator,运行命令 python create_project.py -project MyGame -package com.MyCompany.AwesomeGame -language cpp 即可在cocos2d-x-2.2/projects下生成空白项目,进入项目中查看文件结构,主要有Class文件夹,存放源文件,Resources文件夹存放游戏中需要的图片.音频和配置等资源文件,还有

Cocos2d-x之CCImage深入分析

Cocos2d-x之CCImage深入分析 [Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier] 红孩儿Cocos2d-X学习园地QQ群:249941957 加群写:Cocos2d-x 本节所用Cocos2d-x版本:cocos2d-2.0-x-2.0.2 CCImage类:支持从JPG,PNG,TIFF以及数据流,字符串中创建供Cocos2d-x进行访问的图片数据对象. 这是一个非常重要的类,因为它是你使用co

Linux64位操作系统(CentOS6.6)上如何编译spark1.3

1.在官网下载1.3.0源码后执行如下命令: ./make-distribution.sh --tgz --skip-java-test --with-tachyon -Dhadoop.version=2.4.0 -Djava.version=1.7 -Dprotobuf.version=2.5.0 -Pyarn -Phive -Phive-thriftserver 2.参数说明: --tgz 生成部署包: --skip-java-test 滤过测试阶段: --with-tachyon 感觉ta

【cocos2d-x 3.7 飞机大战】 决战南海I (十二) 游戏结束场景

游戏结束的时候,要显示分数.还要可以选择是返回主场景还是退出游戏 // 退出游戏 void menuCloseCallback(cocos2d::Ref* pSender); // 返回主界面 void menuMainCallback(cocos2d::Ref* pSender); 实现该功能的代码例如以下 bool GameOver::init() { ////////////////////////////// // 1. super init first if (!Layer::init

Spring 整合Redis 出现 afterPropertiesSet signature: ()V) Incompatible argument to function 解决办法

使用的是 spring-data-redis 和 Jedis 配置好之后出现了以下错误: Caused by: java.lang.VerifyError: (class: org/springframework/data/redis/connection/jedis/JedisConnectionFactory, method: afterPropertiesSet signature: ()V) Incompatible argument to function at java.lang.C