我的主题是,有时候知道一些细节会让你写出更好的代码。

============================================

之前学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)妙用的更多相关文章

  1. javaSE基础03

    javaSE基础03 生活中常见的进制:十进制(0-9).星期(七进制(0-6)).时间(十二进制(0-11)).二十四进制(0-23) 进制之间的转换: 十进制转为二进制: 将十进制除以2,直到商为 ...

  2. 从零3D基础入门XNA 4.0(2)——模型和BasicEffect

    [题外话] 上一篇文章介绍了3D开发基础与XNA开发程序的整体结构,以及使用Model类的Draw方法将模型绘制到屏幕上.本文接着上一篇文章继续,介绍XNA中模型的结构.BasicEffect的使用以 ...

  3. 03、NetCore2.0下Web应用之搭建最小框架

    03.NetCore2.0下Web应用之搭建最小框架 这里我们不使用VS2017或者CLI命令的方式创建Asp.Net Core 2.0网页应用程序,而是完全手工的一点点搭建一个Web框架,以便更好的 ...

  4. day33-线程基础03

    线程基础03 6.用户线程和守护线程 用户线程:也叫工作线程,当线程的任务执行完或者通知方法结束.平时用到的普通线程均是用户线程,当在Java程序中创建一个线程,它就被称为用户线程 守护线程(Daem ...

  5. 从零3D基础入门XNA 4.0(1)——3D开发基础

    [题外话] 最近要做一个3D动画演示的程序,由于比较熟悉C#语言,再加上XNA对模型的支持比较好,故选择了XNA平台.不过从网上找到很多XNA的入门文章,发现大都需要一些3D基础,而我之前并没有接触过 ...

  6. javascript基础03

    javascript基础03 1. 算术运算符 后增量/后减量运算符 ++ ,-- 比较运算符 ( >, <, >=, <=, ==, !=,===,!== ) 逻辑运算符( ...

  7. C语言在linux内核中do while(0)妙用之法

    为什么说do while(0) 妙?因为它的确就是妙,而且在linux内核中实现是相当的妙,我们来看看内核中的相关代码: #define db_error(fmt, ...) \ do { \ fpr ...

  8. Thread.Sleep(0)妙用

    Thread.Sleep(0)妙用 我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7  ...

  9. 零基础快速入门SpringBoot2.0 (一)

    零基础快速入门SpringBoot2.0 (一) 一.SpringBoot2.x依赖环境和版本新特性说明 简介:讲解新版本依赖环境和springboot2新特性概述 1.依赖版本jdk8以上, Spr ...

  10. 零基础入门 实战mpvue2.0多端小程序框架

    第1章 课程快速预览(必看!!!)在这一章节中,老师讲带领你快速预览课程整体.其中,涉及到为什么要做这么一门实战课程.制作一个小程序的完整流程是怎么样的,以及如何做项目的技术选型. 第2章 30 分钟 ...

随机推荐

  1. CF 917A The Monster 【括号匹配】

    [链接]:CF Examples inputCopy ((?)) outputCopy 4 inputCopy ??()?? outputCopy 7 说明 For the first sample ...

  2. ZOJ 3332 Strange Country II (竞赛图构造哈密顿通路)

    链接:http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3332 本文链接:http://www.cnblogs.com/Ash-l ...

  3. python3图片验证码识别

    http://my.cnki.net/elibregister/CheckCode.aspx每次刷新该网页可以得到新的验证码进行测试 以我本次查看的验证码图片为例,右键保存图片为image.jpg 下 ...

  4. 差分数组 and 树上差分

    差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易 ...

  5. [BZOJ 1145] 图腾totem

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1145 Solution: 算是一道神题了吧 设 f(abcd)为:当选出的四个数相对大小 ...

  6. codeforces 314E Sereja and Squares

    discription Sereja painted n points on the plane, point number i (1 ≤ i ≤ n) has coordinates (i, 0). ...

  7. BZOJ 3524 [Poi2014]Couriers(可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3524 [题目大意] 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个 ...

  8. 【博弈论】【SG函数】poj2311 Cutting Game

    由于异或运算满足结合律,我们把当前状态的SG函数定义为 它所能切割成的所有纸片对的两两异或和之外的最小非负整数. #include<cstdio> #include<set> ...

  9. 十. 图形界面(GUI)设计10.菜单

    有两种类型的菜单:下拉式菜单和弹出式菜单.本章只讨论下拉式菜单编程方法.菜单与JComboBox和JCheckBox不同,它们在界面中是一直可见的.菜单与JComboBox的相同之处是每次只可选择一个 ...

  10. delphi中使用mediaplayer控件播放音乐

    新建一个名字为media的文件夹,把要播放的音乐文件放在这个文件夹里. ExtractFilePath是用来获得产生的可执行程式所在的路径,因为我们把要播放的音乐文件放在了可执行程式的那个根目录下. ...