嵌套`if`s会提高性能吗?
Posted
技术标签:
【中文标题】嵌套`if`s会提高性能吗?【英文标题】:Does nesting `if`s increase performances? 【发布时间】:2012-12-14 21:25:53 【问题描述】:如果我有这个代码:
if (isFoo() && isBar())
...
程序会先计算第一个条件,再计算第二个条件,然后判断是通过还是跳过下面的块。
但是,如果我像这样嵌套条件:
if (isFoo())
if(isBar())
...
现在它检查第一个条件,如果它是假的,它不会打扰第二个条件。
如果第二个条件(作为一个函数)是一个耗时耗内存的猪,那么嵌套它似乎更好。
这是真的吗?我以前从未见过这样的代码,我在第一个示例之后做了一个假设,但 IMO 很有可能。
【问题讨论】:
见en.wikipedia.org/wiki/Short-circuit_evaluation 这当然不是“与语言无关的”,但大多数语言都会短路布尔值,并且这两个结构是相同的。 @WilliamPursell 感谢您的评论,我已经重新标记了这个问题(希望现在没有问题了)。 【参考方案1】:我相信大多数编译器都会为你做这个优化。如果 && 的第一个条件为假,则不会执行第二个条件。
【讨论】:
【参考方案2】:所有现代语言都会短路任何 AND'ed 子句。所以,在你的例子中,如果 isFoo() 为假,它甚至不会检查 isBar(),它会退出 if 语句。
【讨论】:
不是任何 AND 的子句。有 AND 的子句不会被短路。【参考方案3】:程序会先计算第一个条件,然后再计算第二个条件,
不,不是在大多数现代语言中(例如 C、C++)。由于已知如果第一个条件为假,那么AND
表达式的值不可能是假以外的任何值,因此不计算第二部分。在这两种语言中,标准明确定义了这种优化(称为“短路评估”)。
【讨论】:
有不会短路的AND表达式 @SergeyS 请参阅 William Pursell 的评论。【参考方案4】:在 C#/C++ 和许多其他语言中,实际上有两个逻辑 AND
运算符:&
和 &&
:
&
运算符将评估这两个条件
&&
运算符只会首先计算,如果它等于FALSE
,则它会跳过表达式的第二部分。
这同样适用于逻辑 OR
运算符。有两个运算符:|
和||
:
|
运算符将评估这两个条件
||
运算符只会首先计算,如果它等于TRUE
,则它会跳过表达式的第二部分。
所以,回答您的问题,在您的示例中,您使用的是&&
,它将表现为两个嵌套的if
[EDIT]:好的,要找到使用 of | 的例子并不容易。和 &,我个人在最短代码竞赛中使用过它们))这是它们真正有用的地方(不是因为它们比 && 和 || 短)。还请考虑以下示例:
static bool LaunchFirstRocket()
// Launching rocket if all is ok return true, or return false if we failed to launch it.
static bool LaunchSecondRocket()
// Launching rocket if all is ok return true, or return false if we failed to launch it.
static void Main(string[] args)
if (LaunchFirstRocket() & LaunchSecondRocket())
Console.WriteLine("Both rockets have launched successfully!");
在这里,无论第一个方法的结果如何,我们都将强制执行这两种方法。如果第一颗火箭失败了,我们还想发射第二颗,这是我们的逻辑。是的,还有很多其他方法可以编写此类代码,但这只是教育目的的示例。
【讨论】:
这真的很有趣。有没有我宁愿使用&
或|
的方法?
您需要它们的情况很少见,但根据我的经验,我有这样的情况。我将在我的答案中添加示例
更新了,看看吧,也许这不是最好的例子,只是给个思路。
&
是按位与而不是逻辑运算符,通常在将两个整数“与”时使用它。
@ Christoffer - 不,在 C# 中它表示按位与和逻辑与。这些是分开的。前者的结果是整数,后者的结果是布尔值【参考方案5】:
这取决于。正如其他人所指出的,在带有 short-circuit evaluation 的编译语言(例如 C 和 C++)中,两个版本都可能编译为完全相同的代码。
在某些解释型语言(例如 Perl)中,第二个版本实际上可能比第一个版本非常轻微慢,因为输入代码块的开销很小。例如,这个人工基准清楚地显示了差异:
use Benchmark ':all';
my $count = shift || 10_000_000;
our ($foo, $bar, $baz) = (1, 1, 1);
timethese( $count,
'and' => 'if ($foo && $bar) $baz++; ',
'nested' => 'if ($foo) if ($bar) $baz++; ',
);
输出:
Benchmark: timing 10000000 iterations of and, nested...
and: 2 wallclock secs ( 2.41 usr + 0.00 sys = 2.41 CPU) @ 4149377.59/s (n=10000000)
nested: 4 wallclock secs ( 3.54 usr + 0.00 sys = 3.54 CPU) @ 2824858.76/s (n=10000000)
当然,在实践中,差异可能完全是微不足道的,尤其是与开始使用解释语言的一般开销相比。
【讨论】:
【参考方案6】:这取决于编程语言。
大多数现代/流行语言都支持Short circuit evaluation,这意味着程序不会评估整个表达式,而是在获得整个表达式的结果后立即停止评估(其他人已经给出了示例)。
但也有例外
我知道不支持短路评估的两种语言是 Microsoft VB(6) 和 VB.NET。
VB6 根本不支持,所以这里嵌套If
s 如果常用优化技术。
此外,在像
If Not rs Is Nothing And Not rs.EOF
不使用嵌套If
s 会导致执行错误,而rs
是Nothing
。
VB.NET
引入了两个支持短路评估的新逻辑运算符AndAlso
和OrElse
。
标准 VB.NET
And
和 Or
运算符不支持短路评估,这是新手开发人员常见的错误来源。
优化
在这两种情况下(语言支持而不是短路评估),您都可以检查 表达式按先求值的速度排序。
所以而不是(如果用户是女性,使用偶数键并且已登录,则检查 DB):
if (db.getUserSex() == FEMALE && userKey % 2 == 0 && userKey % 2 && isUserLogged)
使用(检查是否登录(布尔),使用偶数键(算术运算符),最后检查数据库中的性别):
if (isUserLogged && userKey % 2 == 0 && db.getUserSex() == FEMALE)
【讨论】:
以上是关于嵌套`if`s会提高性能吗?的主要内容,如果未能解决你的问题,请参考以下文章