嵌套if会提高性能吗?



如果我有这样的代码:

if (isFoo() && isBar())
{
    ...
}

程序将计算第一个条件,然后计算第二个条件,然后决定是继续执行还是跳过下面的代码块。

但是,如果我像这样嵌套条件:

if (isFoo())
    if(isBar())
    {
        ...
    }

现在检查第一个条件,如果为假,则不检查第二个条件。

如果第二个条件(作为一个函数)是一个耗时的内存开销大的猪头,似乎最好嵌套它。

这是真的吗?我以前从未见过这样的代码,在第一个例子之后我做了一个假设,但在我看来,这是极有可能的。

这取决于编程语言。

大多数现代/流行语言都支持短路求值,这意味着程序不计算整个表达式,而是在得到整个表达式的结果后立即停止求值(其他人已经给出了示例)。

但是也有例外

不支持短路求值的两种语言是Microsoft VB(6)和VB.NET。

VB6根本不支持它,所以这里嵌套If是常用的优化技术。此外,在

这样的表达式中

If Not rs Is Nothing And Not rs.EOF

不使用嵌套If s导致rsNothing时执行错误。

VB.NET引入了两个新的逻辑运算符AndAlsoOrElse,它们支持短路求值。

标准VB.NET AndOr操作符不支持短路求值,这是新手开发人员常见的bug来源。

<标题>最优化h1> 这两种情况下(语言支持和不短路计算),您可以检查顺序的表达式更快地求值第一个

所以,而不是(检查数据库,如果用户是女性,甚至键,它已登录):

if (db.getUserSex() == FEMALE && userKey % 2 == 0 && userKey % 2 && isUserLogged)

use(检查是否登录(boolean),偶数键(算术运算符),并检查DB中的性别):

if (isUserLogged && userKey % 2 == 0 && db.getUserSex() == FEMALE)

在c#/c++和许多其他语言中,实际上有两个逻辑AND运算符:&&&:

&运算符将计算两个条件

&&运算符将只在第一个求值,如果等于FALSE,则跳过表达式的第二部分。

同样也适用于逻辑OR操作符。有两个操作符:|||:

|运算符将计算两个条件

||运算符将只在第一个求值,如果等于TRUE,则跳过表达式的第二部分。

所以,回答你的问题,在你的例子中,你使用的是&&,它将表现为两个嵌套的if

[EDIT]:好吧,找到使用|和&的例子并不容易,我个人在最短代码竞赛中使用过它们))这是它们真正有用的地方(不是因为它们比&&和| |)。还可以考虑以下示例:

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!");
    }
}

无论第一个方法的结果如何,我们都将强制执行两个方法。如果第一枚火箭失败了,我们仍然想发射第二枚,这是我们的逻辑。是的,有很多方法来编写这样的代码,但这只是一个用于教育目的的示例

我相信大多数编译器都会为您做这个优化。如果&&

程序将计算第一个条件,然后计算第二个条件,

不,在大多数现代语言(例如C, c++)中都不是。因为已知如果第一个条件为假,那么AND表达式的值不可能是除假以外的任何值,所以不计算第二部分。在这两种语言中,标准明确地定义了这种优化(称为"短路求值")。

看情况。正如其他人所指出的,在具有短路求值的编译语言中(如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)

当然,在实践中,这种差异可能是完全不重要的,特别是与开始使用解释性语言的一般开销相比。

所有现代语言都会短路任何与子句。所以,在你的例子中,如果isFoo()为假,它甚至不会检查isBar(),它会退出if语句。

相关内容

  • 没有找到相关文章

最新更新