有时在查看代码时,或看到**do{...}while(false)**,会感到很疑惑。为什么要用 do{...}while(false) 呢?
直接写代码不好吗?既然这样写肯定有它的好处,下面写出两种**do{...}while(false)**的用法。
用法1
用于宏定义,可以避免编译器报错,或一些其他错误。请看下面代码:
#define SAFE_DELETE(ptr) if(ptr!=nullptr) delete ptr; //定义一个安全删除指针的宏
//...
//实际中的调用
if(*p1 >5)//假定怕是一个int指针,现在加入有个条件删除值大于5的指针 不然的话就+5
SAFE_DELETE(p1);
else
*p1 += 5;
这个时候问题来了,编译器过不了,报错了,报错如下:
说if和else不匹配,这是为什么?将代码按宏展开:
if(*p1 >5)
if(p1!=nullptr) delete p1; ; //注意这里多了一个;号
else
*p1 += 5;
多了一个;号编译直接就给报错了。有人会说用{}括起来啊,用{}也是一样的,语法有问题。
当然不止这么一个好处。如果你用宏定义一套函数,例如:
#define Funcs() f1();f2();
//实际调用可能这个样子
if(condition)
funcs();
在这里展开后会
if(condition)
f1();f2();;
//也就是
if(condition)
f1();
f2();;
这里会造成很明显的代码逻辑错误。
如果使用do{…}while(false)结构将宏定义为:
#define SAFE_DELETE(ptr) do{if(ptr!=nullptr) delete ptr;}while(false)
就可以很好解决这个问题,在这里就不给大家展开了,可以自己下去展开后,推一下;
用法2
用于条件判断,在很多条件不满足的时候,不会进行后续的代码,先请看下面的代码;
if(condition1)
{
if(condition2)
{
if(condition3)
{
//代码段
}
}
}
在这里使用正常的if结构,会显得代码比较冗余,可读性并非很强。当然这里有人会说,你就不知道用condition1&&condition2&&condition3 吗?在上面的代码是可以的,那么请看下面的代码。
if(condition1)
{
//代码段1
if(condition2)
{
//代码段2
if(condition3)
{
//代码段3
}
}
}
如果你的代码是上面这种情况,就不能使用condition1&&condition2&&condition3。这个时候我们把它改造成do{…}while(false)会怎么样呢?
do
{
if(!condition1)
break;
//代码段1
if(!condition2)
break;
//代码段2
if(!condition3)
break;
//代码段3
}while(false)
很明显可以看出,写成do{…}while(false)结构之后,代码可读性提高不少,在这里我们主要使用的是do{…}while(false)的break:跳转,在这里使用goto也可以达到类似的效果,但是goto已经被大部分程序员弃用了,所以感觉goto看起来不是那么舒服。