6

相关问题使用短路评估的好处为什么语言不使用短路评估?,有人可以解释一下这行代码吗?(逻辑和赋值运算符)

关于使用短路代码的语言的好处存在一些问题,但我想知道对程序员有什么好处?只是它可以让代码更简洁一点吗?还是有性能原因?

我不是在问无论如何都需要评估两个实体的情况,例如:

if($user->auth() AND $model->valid()){
  $model->save();
}

对我来说,推理很清楚 - 因为两者都需要为真,如果用户无法保存数据,您可以跳过成本更高的模型验证。

这也有一个(对我来说)明显的目的:

if(is_string($userid) AND strlen($userid) > 10){
  //do something
};

strlen()因为使用非字符串值调用是不明智的。

我想知道的是当它不影响任何其他语句时使用短路代码。例如,从 Zend Application 默认索引页面:

defined('APPLICATION_PATH')
 || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

这可能是:

if(!defined('APPLICATION_PATH')){
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
}

甚至作为一个单一的声明:

if(!defined('APPLICATION_PATH'))
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

那么为什么要使用短路代码呢?只是为了使用逻辑运算符代替控制结构的“酷”因素?合并嵌套的 if 语句?因为它更快?

4

9 回答 9

4

用它来迷惑人!

于 2009-11-16T20:30:39.800 回答
4

我不了解 PHP,而且我从未见过在 C 语言家族的 if 或 while 条件之外使用短路,但在 Perl 中,这样说是非常惯用的:

open my $filehandle, '<', 'filename' or die "Couldn't open file: $!";

在一个语句中包含所有内容的一个优点是变量声明。否则你不得不说:

my $filehandle;
unless (open $filehandle, '<', 'filename') {
    die "Couldn't open file: $!";
}

在这种情况下,很难说第二个更干净。而且它仍然用一种没有的语言会更加冗长unless

于 2009-11-16T20:31:09.067 回答
4

对于程序员来说,相对于另一种更冗长的语法而言,不太冗长的语法的好处是:

  • 更少的类型,因此更高的编码效率
  • 更少阅读,因此更好的可维护性。

现在我只是在谈论不那么冗长的语法在任何方面都不棘手或聪明的时候,只是同样公认的做事方式,但字符更少。

通常,当您看到一种语言中的特定结构时,您希望您使用的语言可以具有,但以前甚至不一定意识到这一点。我脑海中的一些例子:

  • Java 中的匿名内部类,而不是传递指向函数的指针(代码行更多)。
  • 在 Ruby 中,||= 运算符用于计算表达式并在其计算结果为 false 或为 null 时分配给它。当然,您可以通过 3 行代码实现相同的目标,但为什么呢?
  • 还有很多...
于 2009-11-16T20:42:38.280 回答
2

我认为您的示例是针对凉爽因素的。没有理由编写这样的代码。

编辑:出于惯用的原因,我这样做没有问题。如果使用一种语言的其他人都使用短路评估来制作每个人都能理解的类似语句的实体,那么您也应该这样做。然而,我的经验是,这种代码很少用 C 系列语言编写。正确的形式只是正常使用“if”语句,它将条件(可能没有副作用)与条件控制的函数调用(可能有很多副作用)分开。

于 2009-11-16T20:31:56.630 回答
2

短路运算符在尚未提及的两种重要情况下很有用:

案例1。假设您有一个指针,它可能是也可能不是NULL,并且您想检查它是否不是NULL,并且它指向的东西不是0。但是,如果指针为 NULL,则不能取消引用该指针。如果没有短路运算符,您将不得不这样做:

if (a != NULL) {
  if (*a != 0) {
    ⋮
  }
}

但是,短路运算符允许您更紧凑地编写此代码:

if (a != NULL && *a != 0) {
  ⋮
}

在某些知识中,如果是,*a不会被评估。aNULL

案例 2。如果要将变量设置为从一系列函数之一返回的非假值,您可以简单地执行以下操作:

my $file = $user_filename ||
           find_file_in_user_path() ||
           find_file_in_system_path() ||
           $default_filename;

如果它存在,这将设置$fileto的值,或者如果它是 true,则设置 的结果,或者......等等。这在 Perl 中可能比在 C 中更常见,但我在 C 中看到过。$user_filenamefind_file_in_user_path()

还有其他用途,包括您上面引用的相当人为的示例。但它们是一个有用的工具,我在用不太复杂的语言编程时错过了它。

于 2009-11-16T21:20:14.913 回答
1

与丹所说的相关,我认为这完全取决于每种编程语言的约定。我看不出有什么区别,所以在每种编程语言中做任何惯用的事情。可能会想到的一件事是,如果您必须进行一系列检查,在这种情况下,短路样式将比 if 样式更清晰。

于 2009-11-16T20:56:10.000 回答
0

如果你有一个昂贵的调用(性能方面)函数,它在右侧返回一个布尔值,你只想在另一个条件为真(或假)时调用它?在这种情况下,短路可以为您节省许多 CPU 周期。由于嵌套的 if 语句更少,它确实使代码更简洁。因此,出于您在问题末尾列出的所有原因。

于 2009-11-16T20:29:20.770 回答
0

事实实际上是性能。编译器中使用短路来消除死代码,从而节省文件大小和执行速度。在运行时,如果结果不影响答案,则短路不会执行逻辑表达式中的剩余子句,从而加快了公式的评估。我正在努力记住一个例子。例如

a 和 b 和 c

此公式中有两个项从左到右求值。

如果 a AND b 的计算结果为 FALSE,则下一个表达式 AND c 可以是 FALSE AND TRUE 或 FALSE AND FALSE。无论 c 的值是多少,两者都评估为 FALSE。因此,编译器在编译格式中不包含 AND c,从而使代码短路。

要回答这个问题,有一些特殊情况,编译器无法确定逻辑表达式是否具有恒定输出,因此不会使代码短路。

于 2009-11-16T21:03:09.360 回答
0

这样想,如果你有这样的声明

if( A AND B )

如果 A 返回 FALSE,您可能只想在极少数特殊情况下评估 B。出于这个原因,不使用短路评估是令人困惑的。

短路评估还通过防止另一个括号缩进使您的代码更具可读性,并且括号有加起来的趋势。

于 2011-12-14T19:23:22.130 回答