将条件语句放在迭代内部是否是一种不好的做法?

3

让我们考虑下面这段代码:

if(x == 0)
{
     for(var i = 0; i < 5; ++ i)
     {
         //do something  
     }
}
else
{
   for(var i = 0; i < 5; ++ i)
     {
         //do something different
     }
}

如你所见,这两个条件都遍历同一个for循环但根据条件执行不同的操作。我的问题是,这样做是否是一种不好的实践:

for(var i = 0; i < 5; ++ i)
{
     if(x == 0){
       // do something
     }else{
        // do something else
     }
}

我认为这可能是一种不好的做法的原因在于,对于循环的每个实例,都会针对第一个片段执行条件检查,然后执行循环。我错了吗?


2
挑剔一点:请注意条件表达式中的 x = 0 赋值。 - doynax
@doynax 我已经提交了一份编辑,但由于某些原因被拒绝了。 - hnefatl
@hnefatl 可能是因为这会改变 OP 代码的行为。我们都知道这可能只是一个笔误,但决定权在于 OP... - Jordi Nebot
2个回答

5
除非你编写的代码必须在高速和超高效的情况下运行,否则请优先考虑代码的可读性而不是效率。在这种情况下,我认为第二个示例更清晰,因为它的代码量更少,并且是一种常见的模式。
我想另一个要考虑的因素是,第二个示例似乎暗示着 x 的值可能会改变,而第一个示例则没有。这值得在附近放置一个注释来解释选择。
我的直觉也同意你的看法,第一个示例可能更有效率,但实际上编译器的优化很可能会轻松处理以上示例 - 它们都很可能在性能方面相等。
这里有一个 相当令人印象深刻的列表,列出了可以对循环进行的优化,以便让你有一个思路,还有分支优化(参见答案),如果循环运行多次,则可能会产生影响。

如果您提供其他类似长循环或嵌套循环的案例示例,效果会更好。这些情况下的结果将非常不同。 - ReadyFreddy
1
@ReadyFreddy 我对编译器优化了解不够,无法提供好的例子 - 不过我会添加一些相关资源的链接,这是个很好的点子。如果你有例子并能将其加入我的回答中,请随意编辑。 - hnefatl
1
@hnefatl:确实。第一种变体通常在优化速度时优先选择,而第二种则在优化大小时优先选择。但要注意,如果在关键代码路径上使用,依赖于优化器的自动托管是脆弱的,因为在一般情况下,证明x是否会通过别名或类似方式更改是不容易的。一个本地副本可能是一个有用的提示,但当然需要程序员证明x是不变的。 - doynax

0

如果你使用

if(x = 0)
{
     for(var i = 0; i < 5; ++ i)
     {
         //do something  
     }
}
else
{
   for(var i = 0; i < 5; ++ i)
     {
         //do something different
     }
}

那么你已经完成了一次比较和一个循环,在作用域内执行5次任务。

当你使用

for(var i =0; i < 5; ++ i)
{
     if(x = 0){
       // do something
     }else{
        // do something else
     }
}

然后是一个循环,在范围内执行5次任务。除此之外,比较也进行了5次。

乍一看,前者的指令数量最少。但编译器/解释器可能通过一次比较来执行优化步骤。但这取决于编译器/解释器。如果您对正在编程的语言的编译器/解释器的工作原理有很好的理解,您可以“滥用”这些知识来编写可读的代码,并且具有良好的优化输出。

另一种选择是使用函数。只有在变量x在整个循环期间保持不变时,这种方法才有用,换句话说:您不会在循环本身中修改它。这是您第一个示例的情况。但是,在第二个示例中:x可以在循环中更改,这导致在循环期间运行if {}else {}块,执行两个不同的函数。

替代方案:首先选择一个函数并在循环中使用它。如果您有许多不同的任务要执行,这可能更有用。只需事先选择一个函数即可。某些编程语言允许这样做,而其他编程语言则不允许。因此,这取决于语言本身。

// check which function to run
variable runThisFunction;
if (x = 0) runThisFunction = { // do something }
else runThisFunction = { // do something else }

// loop 5 times using the function
for(var i =0; i < 5; ++ i)
{
     call runThisFunction with arg i provided.
}

值得注意的是,如果do somethingdo something else改变了x的值,那么它们不是等价的。 - Jordi Nebot
(这里始终假设 OP 实际想表达的是 x == 0 而不是 x = 0 - Jordi Nebot
1
@JordiNebot 是的,但是如果你看第一个例子,你会发现他尝试选择一项任务然后执行5次。当然,在第二个例子中可能会有所不同,其中“x”可以被修改。如果它被更改了,那么我的示例就不再有效了。我明白了,编辑了这篇帖子。 - KarelG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接