C++巧用do...while(0)

在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的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。

 

转载声明: 本文转自 http://tieba.baidu.com/f?kz=263292825 (百度贴吧)

转载于:https://www.cnblogs.com/wdpp/archive/2010/11/23/2386854.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298881.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL Server 分区表 处理海量数据

你是不是也在苦苦寻求优化自己的SQL Server数据库的方法?如果你的数据库里有不少非常大的表格,分区功能能够帮到你很大的忙…… 【IT专家网独家】你是不是也在苦苦寻求优化自己的SQL Server数据库的方法?如果你的数据库里有不少非常大的表格,分区功能能…

php curl实现get请求,PHP中使用curl实现Get和Post请求 | 严佳冬

一、基本结构1、初始化curl_init()2、设置变量curl_setopt() 。最为重要,一切玄妙均在此。有一长串curl参数可供设置,它们能指定URL请求的各个细节。执行并获取结果3、执行curl_exec()4、释放cURL句柄curl_close()二、Get方式实现//初始化$ch curl_init…

第十一周项目3-程序的多文件组织

下面的程序中的代码分别保存在两个文件中,利用多文件的方式组织。 mian.cpp /**Copyright (c) 2014,烟台大学计算机学院*All gight reserved.*文件名称:temp.cpp*作者:邵帅*完成时间:2014年11月5日*版本号:v1.0 */ #in…

st link v2引脚连接_ST-Link资料02_ST-Link固件介绍,及固件命名规则

说明:本文原创作者『strongerHuang』本文首发于微信公众号『嵌入式专栏』,同时也更新在我的个人网站:EmbeddedDevelop一、写在前面一些人可能看了上一篇关于ST-Link的内容,就会产生疑惑。。。ST-Link有那么多硬件版本,…

Redis 使用 Lua 脚本进行原子操作

Redis 使用 Lua 脚本进行原子操作Intro之前写过一篇文章也是 Redis 使用 LUA 脚本实现分布式的 CAS 操作,可以参考:基于 Redis 实现 CAS 操作最近使用 Redis 的时候有一个需求,只有值发生变化的时候才更新,如果要更新的值和现在的…

奇妙的数学动图,美到令人窒息!

全世界只有3.14 % 的人关注了爆炸吧知识来源:制造科技原理,版权原作者所有。如有侵权联系删除!论文查重券 限时免费领 官方授权 安全保障 真实有效点「在看」的人都变好看了哦

matlab井深测量,一种井深测量系统及方法与流程

本申请涉及钻井技术领域:,尤其涉及一种井深测量系统及方法。背景技术::在钻井施工中过程中,施工人员需要实时了解井深的变换情况,因此,需要在钻井的过程中实时对井深进行测量。。目前&#xff0…

Log4Net使用指南

声明:本文内容主要译自Nauman Leghari的Using log4net,亦加入了个人的一点心得(节3.1.4)。请在这里下载示例代码 1 简介 1.1 Log4net的优点: 几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后…

搞怪菜鸟加入域全程图解[为企业部署Windows Server 2008系列十二]

在前面部署完毕了windows server 2008的服务器。那么现在我们需要考虑的是如何将客户端加入域。很多朋友在企业实际生产环境中经常遇到加入域的问题,那么在windows server 2008 域环境中呢,如何排除这些问题,本次课程就以雷人故事的角度专门为…

怎样让电脑速度变快_硬盘在电脑中起什么作用?

计算机中的所有数据都保存在硬盘上, 很简单,硬盘的作用就是存储数据。一、补充:1、移动硬盘(Mobile Hard disk)顾名思义是以硬盘为存储介质,计算机之间交换大容量数据,强调便携性的存储产品。2、市场上绝大多数的移动硬…

Qualcomm平台camera调试移植入门

2019独角兽企业重金招聘Python工程师标准>>> 1 camera基本代码架构 高通平台对于camera的代码组织,大体上还是遵循Android的框架:即上层应用和HAL层交互,高通平台在HAL层里面实现自己的一套管理策略; 在kernel中实现s…

Blazor WebAssembly 应用程序中进行 HTTP 请求

翻译自 Waqas Anwar 2021年5月13日的文章 《Making HTTP Requests in Blazor WebAssembly Apps》 [1]在我的前篇文章《Blazor Server 应用程序中进行 HTTP 请求》中,我介绍了在 Blazor Server 应用程序中进行 HTTP 请求的相关技术,在 Blazor Server App …

AI如果耍起了心眼,人类就像个白痴......

耍小心眼已经不是人类专利了。之前,有一群研究者整理了一个场景的List,细数了AI为了完成任务,而耍的小心眼,或者说作弊。例如,在让AI玩俄罗斯方块的时候,发现最佳完成任务的方式是直接暂停游戏;…

ASP.NET MVC数据验证(上)

关于ASP.NET MVC的验证,用起来很特别,因为MS的封装,使人理解起来很费解。也可能很多人都在Scott Guthrie等人写的一本《ASP.NET MVC 1.0》书中,见过NerdDinner项目中对Dinner对象修改和添加的时的数据验证。但有许多封装的地方&am…

Android 的基本组件之一 Gallery

声明:本人博客纯属个人学习过程中的一些仿写的简单练习记录,其他论坛也有类似内容!(可能不免有错误之处,还望见谅,指出)这是一个最简单可以滑动查看图片的应用程序:首先创建项目名为…

【设计模式】—— 中介者模式Mediator

前言:【模式总览】——————————by xingoo 模式意图 使用一个中介的对象,封装一组对象之间的交互,这样这些对象就可以不用彼此耦合。 这个中介者常常起着中间桥梁的作用,使其他的对象可以利用中介者完成某些行为活动&#…

contos6.5卸载php7,centos8 测地卸载php5.6 与卸载php7

centos8 yum php 默认安装 php7.1.2我想卸载php7 ,安装php5.6yum remove php 无法彻底卸载干净。必须强制删除,使用下面命令查看全部php软件包rpm -qa|grep php,然后安装指定顺序卸载卸载php7.X[rootxxx php-memcached]# rpm -qa | grep phpp…

【招聘(上海)】美团酒店招聘 .NET 高级开发

美团酒店介绍:美团酒店是美团旗下的综合住宿服务平台,始终秉承“帮大家住得更好”的使命。成立以来,屡次刷新中国在线住宿行业新纪录。目前,美团已覆盖超过40万家国内酒店,以及全球200多个国家的50000多个城市。我们求…

mysql数据库主要用来做什么的_水晶头骨用来做什么的?

1927年一个小女孩在挖掘时,发现了一颗人头骨。这颗头骨是用水晶做成的,之后关于水晶头骨之谜一直被人津津乐道,人们一直在猜测水晶头骨用来做什么的?一共有多少个?在小女孩挖到这颗头骨之前,大英博物馆里就…

日本画风超级“诡异”毕业典礼上线,网友:有被吓到,谢谢!

转眼间又到了日本毕业季,四月份本来是日本毕业季。在日本,毕业季是非常仪式感的存在:学校里会满是穿着浴衣、盛装打扮的小哥哥小姐姐,拿着毕业证书,在樱花树下合照。图片来源:日剧《对不起,青春…