如果我有一个布尔表达式来检查
(A && B)
如果发现A是假的,语言是否会费心去检查B?这会因语言而异吗?
我问的原因是我想知道是否检查B即使A是假的也不会
if (A) {
if(B) {
} else {
// code x
}
} else {
// code x
}
比
快一点if (A && B) {
} else {
// code x
}
答案 0 :(得分:4)
这取决于语言。大多数语言都会将A && B
实现为短路运算符,这意味着如果A
求值为false,则永远不会计算B
。有一个detailed list on Wikipedia。
答案 1 :(得分:1)
许多语言(包括几乎所有卷括号语言,如C / C ++ / Java / C#)都提供短路布尔评估。在这些语言中,如果A为假,则不会评估B.您需要查看(或询问)这是否适用于您的特定语言,或者是否有办法(例如,VB有AndAlso
)。
如果您发现您的语言不支持它,您还需要考虑评估B的成本是否值得维护两个相同的代码片段 - 以及缓存占用空间可能增加一倍(更不用说所有额外的分支)都来自每次重复。
答案 2 :(得分:1)
几乎每种语言都实现了一种名为short-circuit evaluation的东西,这意味着,如果A为假,则A(& B)将不会评估B.如果你写:
,这也会生效if (A || B) {
...
}
和A是真的。如果B可能需要很长时间才能加载,这是值得记住的,但通常不需要担心。
作为一段历史,在我看来,这是LISP的一个痛处,因为这样的代码:
(if (and (= x 5) (my-expensive-query y)) "Yes" "No")
不是由函数组成,而是所谓的“特殊形式”(即“和”在这里无法解析)。
答案 3 :(得分:1)
这将取决于语言编译所述代码的方式。 任何都是可能的:)
你想知道某种语言吗?
答案 4 :(得分:1)
简而言之,没有。双分支涉及各种形式的分支预测。如果A和B很容易评估,那么如果(A& B)以非短路方式进行(A& B)比如果(A)进行(B)则更快。此外,您在第二种形式中复制了代码。这实际上总是(每个规则的例外......我猜)不好,甚至比任何收益都差。
其次,这是您为语言解释器,JIT或编译器提供的一种微优化。
答案 5 :(得分:0)
正如其他人所说,这取决于语言和/或编译器。对我来说,我不关心短路与否的速度或速度,重复代码的需要是一个交易杀手。
如果A和B实际上是具有副作用的调用(即它们不仅仅返回一个适合比较的值),那么我认为这些调用应该变成可变赋值,然后在比较中使用。无论您是否总是需要这些副作用或只是有条件地要求它们,如果您不依赖于是否存在短路,代码将更具可读性。
关于可读性的最后一点是基于我的感觉,即减少引用外部文档的需要提高了可读性。当你已经拥有必要的词汇时,阅读一本需要字典查找的新词比阅读同一本书更具挑战性。在这种情况下,短路是不可见的,所以任何需要查看的人都不会知道他们需要查找它。