专栏首页米扑专栏C++巧用do...while(0)

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 (百度贴吧)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在windows程序中嵌入Lua脚本引擎--使用VS IDE编译Luajit脚本引擎

            前些天听到一个需求:某业务方需要我们帮忙清理用户电脑上的一些废弃文件。同事完成这个逻辑的方案便是在我们程序中加入了一个很“独立”的业务逻辑:检索...

    方亮
  • 一种精确从文本中提取URL的思路及实现

            在今年三四月份,我接受了一个需求:从文本中提取URL。这样的需求,可能算是非常小众的需求了。大概只有QQ、飞信、阿里旺旺等之类的即时通讯软件存在...

    方亮
  • Windows客户端C/C++编程规范“建议”——前言

            工作中接触了很多编程规范。其中最有意思的是,公司最近发布了一版C/C++编程规范,然后我看到该规范的最后一段时,有这么一句:“该规范不适用于Wi...

    方亮
  • 使用VC实现一个“智能”自增减线程池

            工作中接手了一款产品的改造。因为该产品可能使用很多线程,所以产品中使用了线程池。(转载请指明来自BreakSoftware的CSDN博客)

    方亮
  • WMI技术介绍和应用——VC开发WMI应用的基本步骤

            在《WMI技术介绍和应用——WMI概述》中介绍了我们可以使用C++、.net或者支持ActiveX技术的脚本语言来使用WMI。但是各种语言对WM...

    方亮
  • 可能是最通俗易懂的 Java 位操作运算讲解

    Java 位操作这是一项很基础很基础的知识内容,在所有 Android 和 Java 开发者的学习之路上,大家都接触过,但是实际运用的场景却很少见,很多人估计都...

    Frank909
  • C++17中新特性

    从c++11开始,auto关键字能够通过初始化器推导出变量的类型。在c++14中,auto关键字的能力进一步提升,能够通过return语句推导出函数的返回类型。

    fluyy
  • Xcode10 Pod第三方库找不到lstdc++ 6.0.9

    苹果在XCode10和iOS12中移除了libstdc++这个库,由libc++这个库取而代之,苹果的解释是libstdc++已经标记为废弃有5年了,建议大家使...

    ZY_FlyWay
  • C++拾趣——类构造函数的隐式转换

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csd...

    方亮
  • C++的四种强制转换

            C++中的四种转换,是一个老生常谈的话题。但是对于初学者来说,该如何选择哪种转换方式仍然会有点困惑。而且我总是觉得“纸上得来终觉浅”,于是便“绝...

    方亮

扫码关注云+社区

领取腾讯云代金券