如果我有这段代码:
if (isFoo() && isBar())
{
...
}
程序将计算第一个条件,然后计算第二个条件,然后确定是通过还是跳过下面的块。
但是,如果我像这样嵌套条件:
if (isFoo())
if(isBar())
{
...
}
现在它检查第一个条件,如果它是假的,它不会打扰第二个条件。
如果第二个条件(作为一个函数)是一个耗时的内存昂贵的猪,它似乎更好地嵌套它。
这是真的吗?我以前从未见过这样的代码,我在第一个例子之后做了一个假设,但IMO非常有可能。
答案 0 :(得分:3)
这取决于编程语言。
大多数现代/流行语言支持Short circuit evaluation,这意味着程序不会评估整个表达式,但在获得整个表达式的结果后立即停止评估(其他人已经给出了示例)。
我知道不支持短路评估的两种语言是Microsoft VB(6)和VB.NET。
VB6根本不支持它,所以这里嵌套If
如果常见的优化技术。
此外,在表达式
If Not rs Is Nothing And Not rs.EOF
在If
为rs
时,不使用嵌套Nothing
会导致执行错误。
VB.NET
引入了两个支持短路评估的新逻辑运算符AndAlso
和OrElse
。
标准VB.NET
And
和Or
运算符不支持短路评估,这是新手开发人员的常见错误来源。
在这两种情况下(语言支持而非短路评估),您都可以查看 表达式按更快地评估。
所以代替(如果用户是女性,请检查数据库,使用偶数密钥并登录):
if (db.getUserSex() == FEMALE && userKey % 2 == 0 && userKey % 2 && isUserLogged)
使用(检查是否登录(布尔值),偶数键(算术运算符)并最后检查DB中的性别):
if (isUserLogged && userKey % 2 == 0 && db.getUserSex() == FEMALE)
答案 1 :(得分:2)
在C#/ C ++和许多其他语言中,您实际上有两个逻辑AND
运算符:&
和&&
:
&
运算符将评估这两个条件
&&
运算符只会先评估,如果等于FALSE
,则会跳过表达式的第二部分。
同样适用于逻辑OR
运算符。有两个运算符:|
和||
:
|
运算符将评估这两个条件
||
运算符只会先评估,如果等于TRUE
,则会跳过表达式的第二部分。
所以,回答你的问题,在你的例子中,你正在使用&&
,它将表现为两个嵌套if
的
[编辑] :好的,找到使用|的例子并不容易和我个人在最短的代码比赛中使用它们))这是他们真正有用的地方(不是因为它们比&&和||更短)。还请考虑以下示例:
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!");
}
}
这里我们将强制执行两种方法,而不管第一种方法的结果如何。如果第一次火箭失败,我们仍然想要推出第二次,这是我们的逻辑。是的,有很多很多的其他方式来编写此类代码,但这只是教育目的的一个示例。
答案 2 :(得分:1)
我相信大多数编译器会为你做这个优化。如果&&的第一个条件是假的,第二个不会被执行。
答案 3 :(得分:1)
程序将计算第一个条件,然后计算第二个条件,
不,不是大多数现代语言(例如C,C ++)。因为已知如果第一个条件为假,那么AND
表达式的值不可能是除false之外的任何值,因此不评估第二个部分。在这两种语言中,标准明确定义了这种优化(称为“短路评估”)。
答案 4 :(得分:1)
这取决于。正如其他人所指出的那样,在使用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)
当然,在实践中,差异可能是完全无关紧要的,特别是与使用解释性语言开头的一般开销相比。
答案 5 :(得分:0)
所有现代语言都会使任何AND'ed条款短路。所以,在你的例子中,如果isFoo()为false,它甚至不会检查isBar(),它会退出if语句。