翻译《有关编程、重构及其他的终极问题?》——37.注意在do {...} while (...)中的continue

翻译《有关编程、重构及其他的终极问题?》——37.注意在do {…} while (…)中的continue

标签(空格分隔):翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2018年09月06日


37.注意在do {…} while (…)中的continue

这次的代码摘自Haiku项目(BeOS的继承者)。代码中的错误被PVS-Studio分析器诊断为:V696 The ‘continue’ operator will terminate ‘do { … } while (FALSE)’ loop because the condition is always false(译者注:大意是说循环的判断条件为false所以continue会退出循环)。

do {
  ....
  if (appType.InitCheck() == B_OK
    && appType.GetAppHint(&hintRef) == B_OK
    && appRef == hintRef)
  {
    appType.SetAppHint(NULL);
    // try again
    continue;
  }
  ....
} while (false);

解释

这里continue在do-while循环中工作的方式,并不是很多程序员希望的那样,因为每当执行到continue时,总会检查循环条件是否满足,我将会用更多的细节来解释这点。假设某个程序员写下了下面的代码:

for (int i = 0; i < n; i++)
{
  if (blabla(i))
    continue;
  foo();
}

或写成这样:

while (i < n)
{
  if (blabla(i++))
    continue;
  foo();
}

从直觉上,很多程序员都能理解当执行到continue时,循环控制的判断条件 (i < n) 会被(重新)判断,下面一个循环只有在判断为true的时候才会执行。但让一个程序员写了下面的代码:

do
{
  if (blabla(i++))
    continue;
  foo();
} while (i < n);

这时,直觉就错了,因为他们没有在continue的上面看到判断条件,这样就会让他们理所当然的认为continue会立刻出发下一个循环执行。但事实并非如此,continue还是一如既往触发对判断条件的检查(译者注:即使这个判断条件在continue的下面)。

如果对这种循环中continue的理解缺失是否会造成真的运行错误呢?看运气吧。然而,如果循环判断条件一定时false时,错误就必定发生,就好像开头那段代码一样:那个程序员原计划通过随后的迭代执行一些特定的操作。在注释中的“//try again”清楚的表明了他们的意图。但结果却时没有“again”了,因为判断条件一直是false,所以当执行continue时,循环就结束了。

换句话说,在do {…} while (false)中实用continue,这个continue就等价于break。

正确的代码

可以有很多不同的方式来矫正前述代码。比如,创建一个无穷循环,然后用continue去继续,用break去结束:

for (;;) {
  ....
  if (appType.InitCheck() == B_OK
    && appType.GetAppHint(&hintRef) == B_OK
    && appRef == hintRef)
  {
    appType.SetAppHint(NULL);
    // try again
    continue;
  }
  ....
  break;
};

建议

即使你真的知道以上的问题,也请尽量避免在do {…} while (…)中使用continue。因为你很可能因为不小心而犯这个错误,或者你的同事因为错误理解了你的代码而进行了错误的修改。我永远不会停止说:好的程序员,不是那种炫耀很多不同编程语言技巧的,而是那种能写出清晰、易理解、甚至可以让一个新手都能看懂其代码的。

猜你喜欢

转载自blog.csdn.net/headman/article/details/82459049