do{}while(0)的妙用
来源:互联网 发布:美国国税局 知乎 编辑:程序博客网 时间:2024/04/29 21:10
在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中
作循环时, 我们可能用for和while要多一些,do...while相对不受重视。
但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法
,不是用来做循环,而是用作其他来提高代码的健壮性。
1. do...while(0)消除goto语句。
通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误
则退出函数,当然,退出前先释放资源,我们的代码可能是这样:
version 1
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
// 执行并进行错误处理
bOk = func1();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
bOk = func2();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
bOk = func3();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
// ..........
// 执行成功,释放资源并返回
delete p;
p = NULL;
return true;
}
这里一个最大的问题就是代码的冗余,而且我每增加一个操作,就需要做相应的错误
处理,非常不灵活。于是我们想到了goto:
version 2
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
// 执行并进行错误处理
bOk = func1();
if(!bOk) goto errorhandle;
bOk = func2();
if(!bOk) goto errorhandle;
bOk = func3();
if(!bOk) goto errorhandle;
// ..........
// 执行成功,释放资源并返回
delete p;
p = NULL;
return true;
errorhandle:
delete p;
p = NULL;
return false;
}
代码冗余是消除了,但是我们引入了C++中身份比较微妙的goto语句,虽然正确的使
用goto可以大大提高程序的灵活性与简洁性,但太灵活的东西往往是很危险的,它会
让我们的程序捉摸不定,那么怎么才能避免使用goto语句,又能消除代码冗余呢,请
看do...while(0)循环:
version3
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
do
{
// 执行并进行错误处理
bOk = func1();
if(!bOk) break;
bOk = func2();
if(!bOk) break;
bOk = func3();
if(!bOk) break;
// ..........
}while(0);
// 释放资源
delete p;
p = NULL;
return bOk;
}
“漂亮!”, 看代码就行了,啥都不用说了...
2 宏定义中的do...while(0)
如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的
afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false
), 比如说:
#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal
); __analysis_assume(__afx_condVal); } while(0)
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do...
while(0)有什么意义呢?
当然有!
为了看起来更清晰,这里用一个简单点的宏来演示:
#define SAFE_DELETE(p) do{ delete p; p = NULL} while(0)
假设这里去掉do...while(0),
#define SAFE_DELETE(p) delete p; p = NULL;
那么以下代码:
if(NULL != p) SAFE_DELETE(p)
else ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while, 我直
接用{}括起来就可以了
#define SAFE_DELETE(p) { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句
后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) SAFE_DELETE(p);
else ...do sth...
其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择
了。
也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就
不需要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一
部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮
性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。
作循环时, 我们可能用for和while要多一些,do...while相对不受重视。
但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法
,不是用来做循环,而是用作其他来提高代码的健壮性。
1. do...while(0)消除goto语句。
通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误
则退出函数,当然,退出前先释放资源,我们的代码可能是这样:
version 1
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
// 执行并进行错误处理
bOk = func1();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
bOk = func2();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
bOk = func3();
if(!bOk)
{
delete p;
p = NULL;
return false;
}
// ..........
// 执行成功,释放资源并返回
delete p;
p = NULL;
return true;
}
这里一个最大的问题就是代码的冗余,而且我每增加一个操作,就需要做相应的错误
处理,非常不灵活。于是我们想到了goto:
version 2
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
// 执行并进行错误处理
bOk = func1();
if(!bOk) goto errorhandle;
bOk = func2();
if(!bOk) goto errorhandle;
bOk = func3();
if(!bOk) goto errorhandle;
// ..........
// 执行成功,释放资源并返回
delete p;
p = NULL;
return true;
errorhandle:
delete p;
p = NULL;
return false;
}
代码冗余是消除了,但是我们引入了C++中身份比较微妙的goto语句,虽然正确的使
用goto可以大大提高程序的灵活性与简洁性,但太灵活的东西往往是很危险的,它会
让我们的程序捉摸不定,那么怎么才能避免使用goto语句,又能消除代码冗余呢,请
看do...while(0)循环:
version3
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
do
{
// 执行并进行错误处理
bOk = func1();
if(!bOk) break;
bOk = func2();
if(!bOk) break;
bOk = func3();
if(!bOk) break;
// ..........
}while(0);
// 释放资源
delete p;
p = NULL;
return bOk;
}
“漂亮!”, 看代码就行了,啥都不用说了...
2 宏定义中的do...while(0)
如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的
afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false
), 比如说:
#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal
); __analysis_assume(__afx_condVal); } while(0)
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do...
while(0)有什么意义呢?
当然有!
为了看起来更清晰,这里用一个简单点的宏来演示:
#define SAFE_DELETE(p) do{ delete p; p = NULL} while(0)
假设这里去掉do...while(0),
#define SAFE_DELETE(p) delete p; p = NULL;
那么以下代码:
if(NULL != p) SAFE_DELETE(p)
else ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while, 我直
接用{}括起来就可以了
#define SAFE_DELETE(p) { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句
后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) SAFE_DELETE(p);
else ...do sth...
其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择
了。
也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就
不需要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一
部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮
性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。
0
上一篇:linux错误代码表
下一篇:linux编译及启动过程分析
相关热门文章
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- 什么是shell
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- do/while(0)的妙用
- do/while(0)的妙用
- do/while(0)的妙用
- do...while(0)的妙用
- do/while(0)的妙用
- do/while(0)的妙用
- do...while(0) 的妙用
- do {} while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do...while(0)的妙用
- do{}while(0)的妙用
- do{...}while(0)的妙用
- do...while(0)的妙用
- linux多文件编译方法
- asp.net中验证控件的使用方法
- grep常用方法小结
- urllib2模块
- linux错误代码表
- do{}while(0)的妙用
- linux编译及启动过程分析
- Win7配置theano+cuda8+cudnn实现gpu加速及遇到问题的解决方法
- vim使用技巧
- Echarts3用JS实现保存图片
- tftp服务器的配置
- 国赛题目_寻迹小车调试记录
- HDU2952 (DFS) Counting Sheep
- 博客已升级,请注意变更地址
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
自制纳豆
纳豆好吃吗
日本纳豆
纳豆奶奶
纳豆的功效
纳豆破解版
纳豆破解
纳豆nado
纳豆怎么吃
纳豆精胶囊
纳豆产品
纳豆吃法
纳豆图片
纳豆怎么做
纳豆小僧
纳豆红菊
什么是纳豆
怎么做纳豆
纳豆的吃法
纳豆发酵剂
纳豆怎样吃
纳豆作用
怎样吃纳豆
纳豆机免费
纳豆什么味
如何做纳豆
拉丝纳豆
做纳豆
纳豆哪些人不宜吃
女性吃纳豆有什么好处
自制纳豆的做法
纳豆为什么改名叫菠萝赛东
纳豆什么味道
纳豆机什么牌子好
美丽日记纳豆面膜
浓缩纳豆软胶囊
纳豆的制作方法
纳豆怎么制作
纳豆精的功效
纳豆的功效与作用
纳豆是什么豆子