【C++基础 03】do...while(0)妙用
我的主题是,有时候知道一些细节会让你写出更好的代码。
============================================
之前学coocs2d-x的时候,发现有非常多do...while(0)的写法,一開始不明确为什么如此写,(起不到循环的作用),然后找了一下资料,发现这东西用处还蛮多的。如今来总结一下:
do...while(0)的妙用。
1.避免goto的使用
比方说我们须要在函数中处理一些错误。遇到错误则退出函数。当然退出之前我们须要释放一下资源。比方以下这样子:
bool HelloWorld::init()
{
// 分配资源
int *p = new int;
bool bRet = true; // 运行并进行错误处理
bRet = func1();
if(!bRet)
{
delete p;
p = NULL;
return false;
} bRet = func2();
if(!bRet)
{
delete p;
p = NULL;
return false;
} bRet = func3();
if(!bRet)
{
delete p;
p = NULL;
return false;
} // .......... // 运行成功,释放资源并返回
delete p;
p = NULL;
return true;
}
这样写最大的问题就是代码冗余。每次添加一个操作,就要处理一次,不灵活。所以这时候哦我们想到了goto,然后上面的版本号变成例如以下:
bool HelloWorld::init()
{
// 分配资源
int *p = new int;
bool bRet = true; // 运行并进行错误处理
bRet = func1();
if(!bRet) goto error; bRet = func2();
if(!bRet) goto error; bRet = func3();
if(!bRet) goto error; // 运行成功。释放资源并返回
delete p;
p = NULL;
return true; error:
delete p;
p = NULL;
return false;
}
当然,goto这东西尽管灵活方便,可是非常危急(这就跟红颜祸水这是一个意思,咦。怎么扯上这个了?)所以大部分的书籍都会建议你尽量程序中不要使用这个东西。
所以我们能够使用do...while来消除它。
例如以下:
bool HelloWorld::init()
{
// 分配资源
int *p = new int;
bool bRet = true; do
{
// 运行并进行错误处理
bRet = func1();
if(!bRet) break; bRet = func2();
if(!bRet) break; bRet = func3();
if(!bRet) break; }while(0); // 运行成功,释放资源并返回
delete p;
p = NULL;
return bRet;
}
2.宏定义中的do...while(0)
常常我们能在宏定义中看到这货的影子,比方说cocos2d-x中的
#define CC_SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while(0)
那么又没有循环,也仅仅运行了一次,这样子写有什么意义呢?
假如我们去掉do...while。例如以下:
#define CC_SAFE_DELETE(p) delete (p); (p) = nullptr; if (p != NULL)
CC_SAFE_DELETE(p); //上面会转换成这样子
if (p != NULL)
delete (p);
(p) = nullptr;
如上。第二句永远运行,明显不合意思。有人可能会说,假设再加个括号呢,比方:
#define CC_SAFE_DELETE(p) {delete (p); (p) = nullptr; } //有可能碰到这样的情况
if (p != NULL)
CC_SAFE_DELETE(p);
else
//do else sth //上面会转换成这样
if (p != NULL)
{
delete (p);
(p) = nullptr;
};
else
//do else sth
else直接就编译错误了。
或许你会说,我们代码的习惯是在每一个推断后面加上{}, 就不会有这样的问题了,也就不须要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯。可是我们须要做的是让代码具有通用性,强壮性,因此我们更提倡do...while(0)的使用方法。
========================================
转载请注明出处:http://blog.csdn.net/shun_fzll/article/details/37776429
【C++基础 03】do...while(0)妙用的更多相关文章
- javaSE基础03
javaSE基础03 生活中常见的进制:十进制(0-9).星期(七进制(0-6)).时间(十二进制(0-11)).二十四进制(0-23) 进制之间的转换: 十进制转为二进制: 将十进制除以2,直到商为 ...
- 从零3D基础入门XNA 4.0(2)——模型和BasicEffect
[题外话] 上一篇文章介绍了3D开发基础与XNA开发程序的整体结构,以及使用Model类的Draw方法将模型绘制到屏幕上.本文接着上一篇文章继续,介绍XNA中模型的结构.BasicEffect的使用以 ...
- 03、NetCore2.0下Web应用之搭建最小框架
03.NetCore2.0下Web应用之搭建最小框架 这里我们不使用VS2017或者CLI命令的方式创建Asp.Net Core 2.0网页应用程序,而是完全手工的一点点搭建一个Web框架,以便更好的 ...
- day33-线程基础03
线程基础03 6.用户线程和守护线程 用户线程:也叫工作线程,当线程的任务执行完或者通知方法结束.平时用到的普通线程均是用户线程,当在Java程序中创建一个线程,它就被称为用户线程 守护线程(Daem ...
- 从零3D基础入门XNA 4.0(1)——3D开发基础
[题外话] 最近要做一个3D动画演示的程序,由于比较熟悉C#语言,再加上XNA对模型的支持比较好,故选择了XNA平台.不过从网上找到很多XNA的入门文章,发现大都需要一些3D基础,而我之前并没有接触过 ...
- javascript基础03
javascript基础03 1. 算术运算符 后增量/后减量运算符 ++ ,-- 比较运算符 ( >, <, >=, <=, ==, !=,===,!== ) 逻辑运算符( ...
- C语言在linux内核中do while(0)妙用之法
为什么说do while(0) 妙?因为它的确就是妙,而且在linux内核中实现是相当的妙,我们来看看内核中的相关代码: #define db_error(fmt, ...) \ do { \ fpr ...
- Thread.Sleep(0)妙用
Thread.Sleep(0)妙用 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7 ...
- 零基础快速入门SpringBoot2.0 (一)
零基础快速入门SpringBoot2.0 (一) 一.SpringBoot2.x依赖环境和版本新特性说明 简介:讲解新版本依赖环境和springboot2新特性概述 1.依赖版本jdk8以上, Spr ...
- 零基础入门 实战mpvue2.0多端小程序框架
第1章 课程快速预览(必看!!!)在这一章节中,老师讲带领你快速预览课程整体.其中,涉及到为什么要做这么一门实战课程.制作一个小程序的完整流程是怎么样的,以及如何做项目的技术选型. 第2章 30 分钟 ...
随机推荐
- css样式表中的样式覆盖顺序(转)
有时候在写CSS的过程中,某些限制总是不起作用,这就涉及了CSS样式覆盖的问题,如下 Css代码 #navigator { height: 100%; width: 200; position: ...
- Laravel开启跨域的方法
1.建立中间件Cors.php 命令:php artisan make:middleware Cors 在/app/Http/Middleware/ 目录下会出现一个Cors.php 文件. 内容如下 ...
- pycurl mac 安装报错Curl is configured to use SSL,
1.使用安装第三方插件的方式安装pycurl:pip3 install pycurl 报错提示如下: Curl is configured to use SSL, but we have not be ...
- mysql:把DB1中A表a字段替换为DB2中B表b字段
UPDATE DB1.A SET a = ( SELECT b FROM DB2.B WHERE B.Id = A.id) 实例: UPDATE wordpress.`wp_posts` SET po ...
- python 执行顺序
从上往下顺序执行,定义的方法和类要写在调用之前, 如果有 if __name__ == '__main__' 改方法所在的文件作为启动文件时会被调用,如果作为模块被调用时不会被执行.
- AMQ学习笔记 - 04. 消息选择器
概述 消息选择器使用类似于SQL语法,为Consumer指定基于Message属性的筛选条件. 消息选择器 发送的时候,给消息添加一些属性:在接收的时候,根据属性进行过滤. API javax.jms ...
- NOIP2011选择客栈
n家客栈,1~n编号,每家按照某一种色调装饰,共k种,每家客栈都设有咖啡店,每家咖啡店均有各自的最低消费两位游客,要求住在颜色相同,且不是同一个客栈,在两人的客栈间选择咖啡店(包括他们住的客栈),要求 ...
- Apache用户目录枚举工具apache-users
Apache用户目录枚举工具apache-users Apache服务器提供UserDir模块,允许在网站为不同的用户设置对应的目录.这样,用户可以使用http://example.com/~use ...
- 【数论】【筛法求素数】【欧拉函数】bzoj2818 Gcd
gcd(x,y)(1<=x,y<=n)为素数(暂且把(x,y)和(y,x)算一种) 的个数 <=> gcd(x/k,y/k)=1,k是x的质因数 的个数 <=> Σ ...
- Exercise03_12
import java.util.Scanner; public class Palindrome { public static void main(String[] args){ int a; S ...