if语句在循环中,反之亦然

if statement inside a loop or vice versa

本文关键字:反之亦然 循环 语句 if      更新时间:2023-10-16

我想知道哪种效率更高。

假设我有这个代码:

while (i<10000){
   if (cond1)
      doSomething1();
   else if (cond2)
      doSomething2();
   else
      doSomething3();
}

现在cond1con2是"常数"条件,这意味着如果i发生一次,则所有条件都会发生,并且其中一个条件可能为真。大多数情况下,执行最后一个doSomething3()

现在,如果我写这样的东西会发生什么:

if (cond1){
   while (i<10000)
      doSomething1();
}
else if (cond2){
   while (i<10000)
      doSomething2();
}
else{
   while (i<10000)
      doSomething3();
}

因为我只检查cond1cond2一次,所以它更高效吗?

您需要问的是哪种缓存效率更高。

在许多情况下,编译器可以帮你解决这个问题,并重新排列你的代码以获得最佳结果。它这样做的能力将在很大程度上取决于doSomethingN做什么以及condN是什么。如果condN可以随着时间的推移而变化,那么它可能每次都需要进行物理检查,在这种情况下,您的代码无法进行实质性的重新排列,并且在每次循环迭代中检查它可能确实要慢得多。但是,如果condN是常数,重复的检查可以被优化掉,基本上会导致第一个代码被转换成第二个代码。

最终,唯一可以确定的方法是测量它(如果你能理解的话,研究得到的组装)。

第一次看,第二次看起来更高效,毕竟一次检查显然比10000次检查更高效,好吧,从性能角度来看,更高效的代码是它的价格。

但话说回来,第一个的性能开销可能可以忽略不计,你应该真正对两者进行基准测试,因为你知道,在你证明你有性能问题之前,你不会有性能问题。

无论如何,任何生产级编译器都可能在相当静态且易于分析的上下文中为您优化。

这可能是另一种情况,有更多的选项,在编译时可能无法预测。例如,您可以拥有条件和函数指针的哈希映射,因此您可以查找条件的函数指针,并使用它来调用功能。当然,这将大大降低效率,因为它将使用动态调度,这也意味着调用不能内联,但这是你为使其更灵活而付出的代价,例如,使用这种方法,你可以在运行时注册不同的函数和条件,你可以为给定的条件更改功能等等。

例如,考虑一个场景,您需要执行10000个操作,但每个操作都应该取决于前一个操作的结果。

while (i < 10000) cond = map[cond]();

我想你已经回答了自己的问题。是的,如果编写更高效的代码,效率会更高。

编辑@NeilKirk有道理。由于编译器知道它在做什么,如果编译器能够检测到条件在循环过程中不会改变,那么手动外部检查的效率只有至少和一样高,而不一定比更高。