至“if,if,if”或“if,else if else else if else”

时间:2011-09-14 10:34:26

标签: c++ c if-statement

我正在编写一些数据分析代码,并且必须根据某些标准排除样本。在实践中,我最终编写了如下代码:

bool Test(SampleType sample)
{
  if( ! SubTest1(sample) )
    return false;
  if( ! SubTest2(sample) )
    return false;
  if( ! SubTest3(sample) )
    return false;

  return true;
}

以下似乎与我相同:

bool Test(SampleType sample)
{
  if( ! SubTest1(sample) )
    return false;
  else if( ! SubTest2(sample) )
    return false;
  else if( ! SubTest3(sample) )
    return false;
  else 
    return true;
}

计算成本方面有区别吗?在可扩展性/可维护性,美学等方面是否存在可争议的优先选择......?

我知道这可能是一个无关紧要的问题,但是一旦我把这些问题困在脑子里,我就需要找到答案。

PS:如果有人关心,我在15/09的实际代码可以在以下网址找到: http://folk.uio.no/henrikq/conf.tgz

10 个答案:

答案 0 :(得分:32)

编译器为这两个版本生成相同的代码。但是,如果仅与第二个版本进行比较,第一个版本在可维护性方面会更好。

遇到return语句时,代码退出;所以在即将到来的else中没有使用if。它使开发人员更好地理解代码。

另外,如果这是文字代码,那么你仍然可以缩小为,

bool Test(SampleType sample)
{
  return (SubTest1(sample) && SubTest2(sample) && SubTest3(sample));
}

答案 1 :(得分:29)

我会这样做:

return SubTest1(sample) && SubTest2(sample) && SubTest3(sample);

这不会提高性能,但功能可能会(或可能不会)更明显。

答案 2 :(得分:13)

两者在行为方面完全相同,编译器可能会为两者发出相同的机器代码。

他们在可读性方面甚至没有那么大差别 - 两者都具有相同的嵌套量。将此与no early return leads to deep nesting

的情况进行比较

答案 3 :(得分:5)

就可读性而言,

bool Test( SampleType sample )
{
    return SubTest1( sample )
        && SubTest2( sample )
        && SubTest3( sample );
}

比你的任何一个选项都清楚得多。否则,你肯定 希望else在其中一个条件出现后明确说明 已经满足,其他人都不会被测试。

答案 4 :(得分:2)

两者都是相同的。编译器可能会弄清楚如何优化它们以便发出相同的机器代码。我会争取第一个代码,因为它更容易阅读。

答案 5 :(得分:2)

我无法想象它会对性能产生任何影响。

我会使用第一个,如果它们是独立测试,你只想在它们成功后退出,而第二个如果它在一组逻辑备选之间进行选择则退出。

答案 6 :(得分:0)

据我所知,结果机器代码没有区别。除此之外,谁在乎呢?你有这个代码的性能问题吗?性能是一个困难的主题,通常应该留到项目的最后,并且只有在存在性能问题的情况下才能找到并修复实际存在的地方而不是你提前想到的地方可能是

答案 7 :(得分:0)

它主要取决于编译器如何优化生成的代码。

if(。)通常用compare_to_zero指令翻译,然后是条件跳转。

在您的情况下,这将是

CMP(c1)
RETZ
CMP(c2)
RETZ
CMP(c3)
RETZ

或(使用else-s)

   CMP(c1)
   JNZ(a1)
   RET
a1:CMP(c2)
   JNZ(a2)
   RET
a2:CMP(c3)
   JNZ(a3)
   RET
a3:RET

优化器的第二次传递将看到跳跃链,反转then / else(和Z / NZ)跳过跳跃,位于“跳到下一个”的位置,完全给出前面的代码。 / p>

答案 8 :(得分:0)

这取决于语言和周围的API

第一个解决方案是一种典型的命令式方法,重点是检查一些事情:如果a中止,如果b则中止,如果c则中止,成功。

第二种解决方案是一种功能更强大的方法,可以将其视为数学定义中的大括号(如:fac(n) = { n <= 1: 1, n > 1: n * fac(n-1))。

应选择与环境相匹配的解决方案。在Java,Python等中,它将是第一个。在红宝石中,第二个可能没问题。

答案 9 :(得分:-4)

有一种很好的做法叫做“一个入境点,一个出口点”。这意味着在一个函数中只有一个 return 会更好。

目前,您的功能很简单,但将来可能会增长,变得更复杂,分配必须释放的临时变量等。

所以最好在各地使用好的做法。它被称为“防御性编程”,防御人类失败(我和同事们)。

我会这样写:

bool Test(SampleType sample)
{
  bool bRet = true; // by default, set it to the most "defensive" value which will cause the less harm or make the problem evident

  // in the future, you may have inits and allocations here

  if ( !SubTest1(sample) )
    bRet = false; // don't match
  else if ( !SubTest2(sample) )
    bRet = false; // don't match
  else if ( !SubTest3(sample) )
    bRet = false; // don't match
  else
    ; // bRet stays true

  // thanks to the single point of exit, you can do things like that
  if (bRet)
     log("... match");
  else
     log("...no match")

  // here you clean temporary resources...

  return bRet;
}

如果您想提高性能,最好的方法是将 SubTestX 函数放在最佳状态,以便最常匹配的函数是第一个,因此需要的测试较少发现它不匹配。